aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-25 16:18:11 +0000
committerdnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-25 16:18:11 +0000
commit5b68804772a9757a0ce90fe3f01cdb924f35be1f (patch)
tree4ddceac8bf829506e9798a24ab180536c8aad794
parent9d317bd7d32dcfb729fe94a8d29dc2fa5ac3074b (diff)
Mainline merge rev 180234.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/google/integration@180436 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--contrib/ChangeLog.google-integration5
-rw-r--r--contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail48
-rw-r--r--gcc/ChangeLog2484
-rw-r--r--gcc/ChangeLog.google-integration4
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in11
-rw-r--r--gcc/ada/ChangeLog681
-rw-r--r--gcc/ada/Makefile.rtl12
-rw-r--r--gcc/ada/a-cbhase.adb94
-rw-r--r--gcc/ada/a-cbhase.ads17
-rw-r--r--gcc/ada/a-cbmutr.adb36
-rw-r--r--gcc/ada/a-cbmutr.ads2
-rw-r--r--gcc/ada/a-cborse.adb137
-rw-r--r--gcc/ada/a-cbprqu.adb56
-rw-r--r--gcc/ada/a-cbprqu.ads37
-rw-r--r--gcc/ada/a-cbsyqu.ads10
-rw-r--r--gcc/ada/a-cihase.adb101
-rw-r--r--gcc/ada/a-cihase.ads7
-rw-r--r--gcc/ada/a-ciorma.adb137
-rw-r--r--gcc/ada/a-ciorse.adb129
-rw-r--r--gcc/ada/a-comutr.adb65
-rw-r--r--gcc/ada/a-convec.adb60
-rw-r--r--gcc/ada/a-convec.ads4
-rw-r--r--gcc/ada/a-coorse.adb153
-rw-r--r--gcc/ada/a-csquin.ads16
-rw-r--r--gcc/ada/a-cuprqu.adb54
-rw-r--r--gcc/ada/a-cuprqu.ads55
-rw-r--r--gcc/ada/a-cusyqu.ads10
-rw-r--r--gcc/ada/a-ngcoar.adb590
-rw-r--r--gcc/ada/a-ngcoar.ads2
-rw-r--r--gcc/ada/a-ngrear.adb128
-rw-r--r--gcc/ada/bindgen.adb19
-rw-r--r--gcc/ada/einfo.ads4
-rw-r--r--gcc/ada/exp_aggr.adb17
-rw-r--r--gcc/ada/exp_attr.adb2
-rw-r--r--gcc/ada/exp_ch3.adb371
-rw-r--r--gcc/ada/exp_ch3.ads22
-rw-r--r--gcc/ada/exp_ch4.adb81
-rw-r--r--gcc/ada/exp_ch5.adb14
-rw-r--r--gcc/ada/exp_ch6.adb318
-rw-r--r--gcc/ada/exp_ch6.ads28
-rw-r--r--gcc/ada/exp_ch7.adb2
-rw-r--r--gcc/ada/exp_ch9.adb440
-rw-r--r--gcc/ada/exp_ch9.ads42
-rw-r--r--gcc/ada/exp_disp.adb4
-rw-r--r--gcc/ada/exp_strm.adb6
-rw-r--r--gcc/ada/exp_util.adb4
-rw-r--r--gcc/ada/freeze.adb13
-rw-r--r--gcc/ada/g-debpoo.ads4
-rw-r--r--gcc/ada/g-trasym-unimplemented.adb70
-rw-r--r--gcc/ada/g-trasym-unimplemented.ads64
-rw-r--r--gcc/ada/g-trasym.adb127
-rw-r--r--gcc/ada/g-trasym.ads23
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in93
-rw-r--r--gcc/ada/gcc-interface/Makefile.in73
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h16
-rw-r--r--gcc/ada/gcc-interface/decl.c11
-rw-r--r--gcc/ada/gcc-interface/gigi.h21
-rw-r--r--gcc/ada/gcc-interface/lang-specs.h2
-rw-r--r--gcc/ada/gcc-interface/lang.opt47
-rw-r--r--gcc/ada/gcc-interface/misc.c19
-rw-r--r--gcc/ada/gcc-interface/trans.c637
-rw-r--r--gcc/ada/gcc-interface/utils.c161
-rw-r--r--gcc/ada/gcc-interface/utils2.c93
-rw-r--r--gcc/ada/gnat_ugn.texi564
-rw-r--r--gcc/ada/gnatlink.adb4
-rw-r--r--gcc/ada/impunit.adb2
-rw-r--r--gcc/ada/impunit.ads5
-rw-r--r--gcc/ada/init.c24
-rw-r--r--gcc/ada/lib-xref.adb5
-rw-r--r--gcc/ada/link.c29
-rw-r--r--gcc/ada/make.adb2
-rw-r--r--gcc/ada/mlib-prj.adb30
-rw-r--r--gcc/ada/mlib-utl.adb5
-rw-r--r--gcc/ada/opt.ads10
-rw-r--r--gcc/ada/par-ch12.adb2
-rw-r--r--gcc/ada/par-ch2.adb29
-rw-r--r--gcc/ada/par-ch3.adb34
-rw-r--r--gcc/ada/par-ch5.adb2
-rw-r--r--gcc/ada/par-ch6.adb12
-rw-r--r--gcc/ada/par-util.adb39
-rw-r--r--gcc/ada/par.adb5
-rw-r--r--gcc/ada/prj-conf.adb2
-rw-r--r--gcc/ada/prj-pars.adb2
-rw-r--r--gcc/ada/prj-pars.ads2
-rw-r--r--gcc/ada/prj-part.adb2
-rw-r--r--gcc/ada/prj-part.ads2
-rw-r--r--gcc/ada/prj-proc.adb19
-rw-r--r--gcc/ada/prj-proc.ads2
-rw-r--r--gcc/ada/projects.texi30
-rw-r--r--gcc/ada/rtsfind.ads2
-rw-r--r--gcc/ada/s-gearop.adb178
-rw-r--r--gcc/ada/s-gearop.ads54
-rw-r--r--gcc/ada/s-linux-alpha.ads2
-rw-r--r--gcc/ada/s-linux-sparc.ads2
-rw-r--r--gcc/ada/s-osinte-freebsd.ads5
-rwxr-xr-xgcc/ada/s-regpat.adb10
-rw-r--r--gcc/ada/s-rident.ads2
-rw-r--r--gcc/ada/s-stopoo.ads8
-rw-r--r--gcc/ada/s-taprop-posix.adb19
-rw-r--r--gcc/ada/s-tasren.adb2
-rw-r--r--gcc/ada/s-tpopde-vms.ads4
-rw-r--r--gcc/ada/sem_aggr.adb15
-rw-r--r--gcc/ada/sem_attr.adb29
-rw-r--r--gcc/ada/sem_attr.ads14
-rw-r--r--gcc/ada/sem_cat.adb2
-rw-r--r--gcc/ada/sem_ch10.adb2
-rw-r--r--gcc/ada/sem_ch12.adb33
-rw-r--r--gcc/ada/sem_ch13.adb14
-rw-r--r--gcc/ada/sem_ch3.adb61
-rw-r--r--gcc/ada/sem_ch4.adb104
-rw-r--r--gcc/ada/sem_ch5.adb2
-rw-r--r--gcc/ada/sem_ch6.adb96
-rw-r--r--gcc/ada/sem_ch8.adb9
-rw-r--r--gcc/ada/sem_ch9.adb27
-rw-r--r--gcc/ada/sem_intr.adb10
-rw-r--r--gcc/ada/sem_prag.adb17
-rw-r--r--gcc/ada/sem_res.adb71
-rw-r--r--gcc/ada/sem_res.ads4
-rw-r--r--gcc/ada/sem_type.adb48
-rw-r--r--gcc/ada/sem_util.adb117
-rw-r--r--gcc/ada/sem_util.ads16
-rw-r--r--gcc/ada/sigtramp-ppcvxw.c256
-rw-r--r--gcc/ada/sigtramp.h56
-rw-r--r--gcc/ada/sysdep.c3
-rw-r--r--gcc/ada/vms_data.ads25
-rw-r--r--gcc/builtins.c223
-rw-r--r--gcc/builtins.def8
-rw-r--r--gcc/c-decl.c28
-rw-r--r--gcc/c-family/ChangeLog77
-rw-r--r--gcc/c-family/c-common.c14
-rw-r--r--gcc/c-family/c-common.h5
-rw-r--r--gcc/c-family/c-lex.c10
-rw-r--r--gcc/c-family/c-omp.c8
-rw-r--r--gcc/c-family/c-opts.c16
-rw-r--r--gcc/c-family/c-ppoutput.c100
-rw-r--r--gcc/c-family/c-pretty-print.c14
-rw-r--r--gcc/c-family/c.opt20
-rw-r--r--gcc/c-parser.c270
-rw-r--r--gcc/c-tree.h17
-rw-r--r--gcc/c-typeck.c135
-rw-r--r--gcc/calls.c13
-rw-r--r--gcc/cfgcleanup.c10
-rw-r--r--gcc/cfgexpand.c12
-rw-r--r--gcc/cfgrtl.c2
-rw-r--r--gcc/cgraphunit.c39
-rw-r--r--gcc/combine-stack-adj.c16
-rw-r--r--gcc/combine.c15
-rw-r--r--gcc/common.opt9
-rw-r--r--gcc/compare-elim.c8
-rw-r--r--gcc/config.gcc21
-rw-r--r--gcc/config.host8
-rw-r--r--gcc/config.in13
-rw-r--r--gcc/config/arm/arm-c.c38
-rw-r--r--gcc/config/arm/arm.c775
-rw-r--r--gcc/config/arm/arm.h43
-rw-r--r--gcc/config/arm/arm.md15
-rw-r--r--gcc/config/arm/arm.opt10
-rw-r--r--gcc/config/arm/driver-arm.c149
-rw-r--r--gcc/config/arm/iterators.md12
-rw-r--r--gcc/config/arm/linux-atomic-64bit.c166
-rw-r--r--gcc/config/arm/linux-atomic.c5
-rw-r--r--gcc/config/arm/neon.md66
-rw-r--r--gcc/config/arm/predicates.md19
-rw-r--r--gcc/config/arm/sync.md424
-rw-r--r--gcc/config/arm/t-linux-eabi1
-rw-r--r--gcc/config/arm/x-arm3
-rw-r--r--gcc/config/avr/avr-mcus.def2
-rw-r--r--gcc/config/avr/avr-protos.h7
-rw-r--r--gcc/config/avr/avr.c486
-rw-r--r--gcc/config/avr/avr.h78
-rw-r--r--gcc/config/avr/avr.md626
-rw-r--r--gcc/config/avr/avr.opt4
-rw-r--r--gcc/config/avr/libgcc.S28
-rw-r--r--gcc/config/cris/cris-protos.h1
-rw-r--r--gcc/config/cris/cris.c38
-rw-r--r--gcc/config/cris/cris.h19
-rw-r--r--gcc/config/darwin.c19
-rw-r--r--gcc/config/gnu.h4
-rw-r--r--gcc/config/i386/djgpp.h4
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c2041
-rw-r--r--gcc/config/i386/i386.h13
-rw-r--r--gcc/config/i386/i386.md45
-rw-r--r--gcc/config/i386/i386.opt13
-rw-r--r--gcc/config/i386/mingw-w64.h4
-rw-r--r--gcc/config/i386/mingw32.h11
-rw-r--r--gcc/config/i386/predicates.md9
-rw-r--r--gcc/config/i386/sse.md867
-rw-r--r--gcc/config/i386/t-djgpp2
-rw-r--r--gcc/config/i386/t-mingw-w323
-rw-r--r--gcc/config/i386/t-mingw-w643
-rw-r--r--gcc/config/i386/t-mingw323
-rw-r--r--gcc/config/ia64/ia64.c15
-rw-r--r--gcc/config/m68k/m68k-protos.h1
-rw-r--r--gcc/config/m68k/m68k.c8
-rw-r--r--gcc/config/m68k/m68k.h6
-rw-r--r--gcc/config/mips/mips.c94
-rw-r--r--gcc/config/mips/sync.md14
-rw-r--r--gcc/config/openbsd.h4
-rw-r--r--gcc/config/pa/pa.c21
-rw-r--r--gcc/config/rs6000/aix.h3
-rw-r--r--gcc/config/rs6000/altivec.md9
-rw-r--r--gcc/config/rs6000/rs6000.c12
-rw-r--r--gcc/config/rx/constraints.md22
-rw-r--r--gcc/config/rx/rx-protos.h1
-rw-r--r--gcc/config/rx/rx.c248
-rw-r--r--gcc/config/rx/rx.h32
-rw-r--r--gcc/config/rx/rx.md78
-rw-r--r--gcc/config/rx/rx.opt6
-rw-r--r--gcc/config/rx/t-rx4
-rw-r--r--gcc/config/s390/s390.c20
-rw-r--r--gcc/config/s390/s390.md27
-rw-r--r--gcc/config/sh/sh.c16
-rw-r--r--gcc/config/sh/sh.h3
-rw-r--r--gcc/config/sh/sh.md161
-rw-r--r--gcc/config/sparc/driver-sparc.c2
-rw-r--r--gcc/config/sparc/linux.h2
-rw-r--r--gcc/config/sparc/linux64.h6
-rw-r--r--gcc/config/sparc/predicates.md5
-rw-r--r--gcc/config/sparc/sol2.h2
-rw-r--r--gcc/config/sparc/sparc-modes.def4
-rw-r--r--gcc/config/sparc/sparc-protos.h3
-rw-r--r--gcc/config/sparc/sparc.c589
-rw-r--r--gcc/config/sparc/sparc.h15
-rw-r--r--gcc/config/sparc/sparc.md1557
-rw-r--r--gcc/config/sparc/sparc.opt17
-rw-r--r--gcc/config/sparc/visintrin.h63
-rw-r--r--gcc/config/spu/spu-elf.h5
-rw-r--r--gcc/config/spu/spu.c105
-rw-r--r--gcc/config/spu/spu.md12
-rw-r--r--gcc/config/spu/t-spu-elf4
-rw-r--r--gcc/config/t-gnu2
-rw-r--r--gcc/config/vms/vms.c7
-rw-r--r--gcc/config/vms/xm-vms.h3
-rwxr-xr-xgcc/configure166
-rw-r--r--gcc/configure.ac53
-rw-r--r--gcc/convert.c9
-rw-r--r--gcc/cp/ChangeLog285
-rw-r--r--gcc/cp/call.c42
-rw-r--r--gcc/cp/class.c93
-rw-r--r--gcc/cp/cp-objcp-common.c1
-rw-r--r--gcc/cp/cp-tree.def5
-rw-r--r--gcc/cp/cp-tree.h46
-rw-r--r--gcc/cp/cxx-pretty-print.c2
-rw-r--r--gcc/cp/decl.c86
-rw-r--r--gcc/cp/error.c6
-rw-r--r--gcc/cp/except.c4
-rw-r--r--gcc/cp/init.c74
-rw-r--r--gcc/cp/method.c74
-rw-r--r--gcc/cp/parser.c392
-rw-r--r--gcc/cp/parser.h4
-rw-r--r--gcc/cp/pt.c758
-rw-r--r--gcc/cp/semantics.c213
-rw-r--r--gcc/cp/tree.c10
-rw-r--r--gcc/cp/typeck.c30
-rw-r--r--gcc/cp/typeck2.c5
-rw-r--r--gcc/cppdefault.c22
-rw-r--r--gcc/diagnostic.c24
-rw-r--r--gcc/diagnostic.h2
-rw-r--r--gcc/doc/cppopts.texi31
-rw-r--r--gcc/doc/extend.texi56
-rw-r--r--gcc/doc/fragments.texi9
-rw-r--r--gcc/doc/install.texi6
-rw-r--r--gcc/doc/invoke.texi179
-rw-r--r--gcc/doc/md.texi45
-rw-r--r--gcc/doc/objc.texi3
-rw-r--r--gcc/doc/tm.texi42
-rw-r--r--gcc/doc/tm.texi.in42
-rw-r--r--gcc/dwarf2out.c3
-rw-r--r--gcc/emit-rtl.c6
-rw-r--r--gcc/expmed.c4
-rw-r--r--gcc/expr.c198
-rw-r--r--gcc/expr.h2
-rw-r--r--gcc/fold-const.c154
-rw-r--r--gcc/fortran/ChangeLog394
-rw-r--r--gcc/fortran/ChangeLog-200826
-rw-r--r--gcc/fortran/ChangeLog-20098
-rw-r--r--gcc/fortran/ChangeLog-20102
-rw-r--r--gcc/fortran/Make-lang.in6
-rw-r--r--gcc/fortran/array.c3
-rw-r--r--gcc/fortran/check.c49
-rw-r--r--gcc/fortran/class.c2
-rw-r--r--gcc/fortran/cpp.c22
-rw-r--r--gcc/fortran/decl.c24
-rw-r--r--gcc/fortran/expr.c26
-rw-r--r--gcc/fortran/f95-lang.c10
-rw-r--r--gcc/fortran/frontend-passes.c34
-rw-r--r--gcc/fortran/gfortran.h8
-rw-r--r--gcc/fortran/gfortran.texi45
-rw-r--r--gcc/fortran/interface.c43
-rw-r--r--gcc/fortran/intrinsic.c8
-rw-r--r--gcc/fortran/intrinsic.texi17
-rw-r--r--gcc/fortran/invoke.texi24
-rw-r--r--gcc/fortran/iso-c-binding.def24
-rw-r--r--gcc/fortran/lang.opt4
-rw-r--r--gcc/fortran/libgfortran.h2
-rw-r--r--gcc/fortran/module.c107
-rw-r--r--gcc/fortran/options.c6
-rw-r--r--gcc/fortran/primary.c39
-rw-r--r--gcc/fortran/resolve.c163
-rw-r--r--gcc/fortran/simplify.c6
-rw-r--r--gcc/fortran/symbol.c6
-rw-r--r--gcc/fortran/trans-array.c302
-rw-r--r--gcc/fortran/trans-array.h2
-rw-r--r--gcc/fortran/trans-common.c10
-rw-r--r--gcc/fortran/trans-decl.c7
-rw-r--r--gcc/fortran/trans-expr.c44
-rw-r--r--gcc/fortran/trans-intrinsic.c146
-rw-r--r--gcc/fortran/trans-openmp.c13
-rw-r--r--gcc/fortran/trans-stmt.c8
-rw-r--r--gcc/fortran/trans-types.c14
-rw-r--r--gcc/fortran/trans-types.h1
-rw-r--r--gcc/fortran/trans.c35
-rw-r--r--gcc/fortran/trans.h8
-rw-r--r--gcc/function.c912
-rw-r--r--gcc/function.h3
-rw-r--r--gcc/gengtype.c5
-rw-r--r--gcc/genopinit.c6
-rw-r--r--gcc/ggc-none.c9
-rw-r--r--gcc/ggc-page.c106
-rw-r--r--gcc/ggc-zone.c27
-rw-r--r--gcc/ggc.h2
-rw-r--r--gcc/gimple-fold.c161
-rw-r--r--gcc/gimple-low.c6
-rw-r--r--gcc/gimple-pretty-print.c14
-rw-r--r--gcc/gimple.c25
-rw-r--r--gcc/gimplify.c41
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc8
-rw-r--r--gcc/go/gofrontend/gogo.cc5
-rw-r--r--gcc/godump.c17
-rw-r--r--gcc/hooks.c8
-rw-r--r--gcc/hooks.h1
-rw-r--r--gcc/ifcvt.c58
-rw-r--r--gcc/input.c107
-rw-r--r--gcc/input.h20
-rw-r--r--gcc/ipa-inline-analysis.c4
-rw-r--r--gcc/ipa-pure-const.c1
-rw-r--r--gcc/ipa-split.c28
-rw-r--r--gcc/java/ChangeLog21
-rw-r--r--gcc/java/builtins.c26
-rw-r--r--gcc/java/class.c2
-rw-r--r--gcc/java/decl.c2
-rw-r--r--gcc/java/except.c4
-rw-r--r--gcc/java/expr.c14
-rw-r--r--gcc/java/jcf-parse.c2
-rw-r--r--gcc/jump.c3
-rw-r--r--gcc/longlong.h25
-rw-r--r--gcc/lto-cgraph.c19
-rw-r--r--gcc/lto-streamer-in.c107
-rw-r--r--gcc/lto-streamer-out.c93
-rw-r--r--gcc/lto-streamer.h2
-rw-r--r--gcc/lto/ChangeLog29
-rw-r--r--gcc/lto/lto-lang.c4
-rw-r--r--gcc/lto/lto-object.c17
-rw-r--r--gcc/lto/lto.c81
-rw-r--r--gcc/lto/lto.h10
-rw-r--r--gcc/modulo-sched.c921
-rw-r--r--gcc/objc/ChangeLog70
-rw-r--r--gcc/objc/Make-lang.in10
-rw-r--r--gcc/objc/config-lang.in2
-rw-r--r--gcc/objc/objc-act.c507
-rw-r--r--gcc/objc/objc-act.h6
-rw-r--r--gcc/objc/objc-gnu-runtime-abi-01.c2
-rw-r--r--gcc/objc/objc-map.c161
-rw-r--r--gcc/objc/objc-map.h309
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c2
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c3
-rw-r--r--gcc/objcp/ChangeLog7
-rw-r--r--gcc/objcp/Make-lang.in10
-rw-r--r--gcc/objcp/config-lang.in2
-rw-r--r--gcc/omp-low.c162
-rw-r--r--gcc/optabs.c279
-rw-r--r--gcc/optabs.h22
-rw-r--r--gcc/opts.c1
-rw-r--r--gcc/passes.c2
-rw-r--r--gcc/plugin.c4
-rw-r--r--gcc/po/ChangeLog4
-rw-r--r--gcc/po/de.po344
-rw-r--r--gcc/profile.c41
-rw-r--r--gcc/regrename.c294
-rw-r--r--gcc/regrename.h101
-rw-r--r--gcc/reorg.c2
-rw-r--r--gcc/rtl.h22
-rw-r--r--gcc/sel-sched-ir.c5
-rw-r--r--gcc/sel-sched.c20
-rw-r--r--gcc/stmt.c113
-rw-r--r--gcc/streamer-hooks.h10
-rw-r--r--gcc/system.h9
-rw-r--r--gcc/target.def2
-rw-r--r--gcc/targhooks.c15
-rw-r--r--gcc/targhooks.h2
-rw-r--r--gcc/testsuite/ChangeLog1066
-rw-r--r--gcc/testsuite/c-c++-common/cxxbitfields-2.c19
-rw-r--r--gcc/testsuite/c-c++-common/cxxbitfields-4.c18
-rw-r--r--gcc/testsuite/c-c++-common/cxxbitfields-5.c29
-rw-r--r--gcc/testsuite/c-c++-common/cxxbitfields.c18
-rw-r--r--gcc/testsuite/c-c++-common/simulate-thread/bitfields-1.c71
-rw-r--r--gcc/testsuite/c-c++-common/simulate-thread/bitfields-2.c59
-rw-r--r--gcc/testsuite/c-c++-common/simulate-thread/bitfields-3.c63
-rw-r--r--gcc/testsuite/c-c++-common/simulate-thread/bitfields-4.c60
-rw-r--r--gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted20.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted31.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted32.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit-copy.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit12.C54
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit4.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit5.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit8.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/not_special.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi5.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for22.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv1n.C34
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv2n.C110
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv3n.C202
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv4n.C230
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv5n.C170
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv6n.C74
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv7n.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic105.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic117.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic118.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic35.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic65.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic82.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic83.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/bases.C35
-rw-r--r--gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C9
-rw-r--r--gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C2
-rw-r--r--gcc/testsuite/g++.dg/inherit/error5.C14
-rw-r--r--gcc/testsuite/g++.dg/init/ref20.C8
-rw-r--r--gcc/testsuite/g++.dg/init/value9.C32
-rw-r--r--gcc/testsuite/g++.dg/init/vbase1.C39
-rw-r--r--gcc/testsuite/g++.dg/lookup/using23.C13
-rw-r--r--gcc/testsuite/g++.dg/other/final1.C1
-rw-r--r--gcc/testsuite/g++.dg/other/pr47218.C2
-rw-r--r--gcc/testsuite/g++.dg/overload/operator4.C14
-rw-r--r--gcc/testsuite/g++.dg/parse/error20.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error41.C11
-rw-r--r--gcc/testsuite/g++.dg/parse/error42.C4
-rw-r--r--gcc/testsuite/g++.dg/pr48660.C22
-rw-r--r--gcc/testsuite/g++.dg/simulate-thread/simulate-thread.exp39
-rw-r--r--gcc/testsuite/g++.dg/simulate-thread/simulate-thread.gdb1
-rw-r--r--gcc/testsuite/g++.dg/simulate-thread/simulate-thread.h1
-rw-r--r--gcc/testsuite/g++.dg/template/constant1.C13
-rw-r--r--gcc/testsuite/g++.dg/template/constant2.C22
-rw-r--r--gcc/testsuite/g++.dg/torture/pr50189.C121
-rw-r--r--gcc/testsuite/g++.dg/vect/pr50698.cc27
-rw-r--r--gcc/testsuite/g++.dg/warn/format5.C12
-rw-r--r--gcc/testsuite/g++.dg/warn/format6.C7
-rw-r--r--gcc/testsuite/g++.dg/warn/format7.C10
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr49049.c28
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr50565-1.c4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr50565-2.c4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr50650.c10
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr49279.c35
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vector-compare-2.x2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-16.inc81
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-2.inc38
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-4.inc39
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-8.inc101
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-main.inc26
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v16qi.c5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v2df.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v2di.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v2sf.c21
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v2si.c18
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v4df.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v4di.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v4hi.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v4sf.c25
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v4si.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v8hi.c23
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v8qi.c23
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v8si.c30
-rw-r--r--gcc/testsuite/gcc.dg/builtin-complex-err-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/builtin-object-size-12.c19
-rw-r--r--gcc/testsuite/gcc.dg/builtins-47.c2
-rw-r--r--gcc/testsuite/gcc.dg/builtins-67.c4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c14
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c14
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c32
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c34
-rw-r--r--gcc/testsuite/gcc.dg/di-longlong64-sync-1.c164
-rw-r--r--gcc/testsuite/gcc.dg/di-sync-multithread.c205
-rw-r--r--gcc/testsuite/gcc.dg/graphite/id-pr46845.c2
-rw-r--r--gcc/testsuite/gcc.dg/graphite/interchange-14.c2
-rw-r--r--gcc/testsuite/gcc.dg/graphite/interchange-15.c2
-rw-r--r--gcc/testsuite/gcc.dg/graphite/interchange-mvt.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/inline-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/lto/20081222_1.c8
-rw-r--r--gcc/testsuite/gcc.dg/memcpy-4.c11
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir1.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir2.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir3.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir4.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr47276.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr49696.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr49994-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr50193-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr50205.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr50340.c46
-rw-r--r--gcc/testsuite/gcc.dg/pr50527.c46
-rw-r--r--gcc/testsuite/gcc.dg/pr50604.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr50613.c20
-rw-r--r--gcc/testsuite/gcc.dg/pr50717-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/README118
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.exp38
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.gdb17
-rw-r--r--gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.h111
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-21.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-complex-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr48044.c8
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50389.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50723.c26
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50729.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50767.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50768.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/restrict-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-16.inc133
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-2.inc19
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-32.inc133
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-4.inc133
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-8.inc133
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-main.inc55
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2df.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2di.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2si.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4df.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4di.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4si.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8si.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/restrict-4.c26
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-35.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-36.c26
-rw-r--r--gcc/testsuite/gcc.dg/uninit-B.c2
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr19430.c4
-rw-r--r--gcc/testsuite/gcc.dg/va-arg-4.c3
-rw-r--r--gcc/testsuite/gcc.dg/va-arg-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-29.c59
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr50635.c21
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr50727.c21
-rw-r--r--gcc/testsuite/gcc.dg/vect/vec-scal-opt.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-114.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-21.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-align-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cond-8.c122
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cond-9.c200
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c107
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c58
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c58
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c65
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect.exp10
-rw-r--r--gcc/testsuite/gcc.dg/vla-23.c17
-rw-r--r--gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c14
-rw-r--r--gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c17
-rw-r--r--gcc/testsuite/gcc.target/arm/pr50305.c60
-rw-r--r--gcc/testsuite/gcc.target/arm/shiftable.c63
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c19
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c21
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c21
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c18
-rw-r--r--gcc/testsuite/gcc.target/arm/wmul-12.c4
-rw-r--r--gcc/testsuite/gcc.target/arm/wmul-8.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpand-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpop-check.h53
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_1.h101
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_2.h101
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_3.h101
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_4.h101
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_5.h101
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_6.h101
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_2.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_3.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_4.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_5.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_2.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_3.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_4.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_5.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_main.h117
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_3.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_4.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_5.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_6.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_results_1.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_results_2.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_results_3.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_results_4.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_results_5.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_results_6.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_3.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_4.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_5.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_6.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_results_1.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_results_2.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_results_3.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_results_4.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_results_5.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_results_6.h54
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_1.h133
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_2.h133
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_3.h133
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_4.h133
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_5.h133
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_6.h133
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_1.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_3.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_4.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_5.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_6.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_1.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_3.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_4.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_5.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_6.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_main.h100
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr50603.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr50712.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mul-1.c209
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/sw-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/warn-vect-op-1.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/warn-vect-op-2.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/warn-vect-op-3.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/mips/abi-o64-long64.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/mips.exp64
-rw-r--r--gcc/testsuite/gcc.target/mips/stack-1.c11
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-pow.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-3.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-4.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-5.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/warn-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/warn-2.c1
-rw-r--r--gcc/testsuite/gcc.target/s390/20090223-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sparc/cmask.c2
-rw-r--r--gcc/testsuite/gcc.target/sparc/fand.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/fandnot.c20
-rw-r--r--gcc/testsuite/gcc.target/sparc/fhalve.c39
-rw-r--r--gcc/testsuite/gcc.target/sparc/fnegop.c33
-rw-r--r--gcc/testsuite/gcc.target/sparc/fnot.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/for.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/fornot.c21
-rw-r--r--gcc/testsuite/gcc.target/sparc/fpadds.c2
-rw-r--r--gcc/testsuite/gcc.target/sparc/fshift.c2
-rw-r--r--gcc/testsuite/gcc.target/sparc/fucmp.c2
-rw-r--r--gcc/testsuite/gcc.target/sparc/fxnor.c20
-rw-r--r--gcc/testsuite/gcc.target/sparc/fxor.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/lzd.c18
-rw-r--r--gcc/testsuite/gcc.target/sparc/popc.c18
-rw-r--r--gcc/testsuite/gcc.target/sparc/sparc.exp11
-rw-r--r--gcc/testsuite/gcc.target/sparc/vis3misc.c2
-rw-r--r--gcc/testsuite/gcc.target/sparc/xmul.c22
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_usage_22.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_usage_23.f908
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_usage_24.f902
-rw-r--r--gcc/testsuite/gfortran.dg/c_kind_tests_3.f0311
-rw-r--r--gcc/testsuite/gfortran.dg/c_sizeof_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/class_46.f0318
-rw-r--r--gcc/testsuite/gfortran.dg/coarray/subobject_1.f9043
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_subobject_1.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/common_14.f901
-rw-r--r--gcc/testsuite/gfortran.dg/common_16.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/dummy_procedure_6.f9071
-rw-r--r--gcc/testsuite/gfortran.dg/elemental_args_check_4.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/forall_15.f9026
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_class.f0315
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_param_1.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_param_2.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/kind_tests_4.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_check_11.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_check_12.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_function_result_1.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_intent_5.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/proc_decl_27.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/rank_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/rank_4.f902
-rw-r--r--gcc/testsuite/gfortran.dg/sizeof_proc.f9028
-rw-r--r--gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f9010
-rw-r--r--gcc/testsuite/gnat.dg/specs/debug1.ads2
-rw-r--r--gcc/testsuite/gnat.dg/vect1.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect1.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect1_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect2.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect2.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect2_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect3.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect3.ads43
-rw-r--r--gcc/testsuite/gnat.dg/vect3_pkg.ads10
-rw-r--r--gcc/testsuite/gnat.dg/vect4.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect4.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect4_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect5.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect5.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect5_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect6.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect6.ads43
-rw-r--r--gcc/testsuite/gnat.dg/vect6_pkg.ads10
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp22
-rw-r--r--gcc/testsuite/lib/gcc-gdb-test.exp7
-rw-r--r--gcc/testsuite/lib/gcc-simulate-thread.exp90
-rw-r--r--gcc/testsuite/lib/prune.exp1
-rw-r--r--gcc/testsuite/lib/target-supports.exp160
-rw-r--r--gcc/testsuite/obj-c++.dg/warn6.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/warn7.mm10
-rw-r--r--gcc/testsuite/objc/execute/initialize-1.m47
-rw-r--r--gcc/toplev.c11
-rw-r--r--gcc/tree-cfg.c91
-rw-r--r--gcc/tree-complex.c2
-rw-r--r--gcc/tree-data-ref.c3
-rw-r--r--gcc/tree-dfa.c3
-rw-r--r--gcc/tree-diagnostic.c182
-rw-r--r--gcc/tree-diagnostic.h3
-rw-r--r--gcc/tree-eh.c24
-rw-r--r--gcc/tree-emutls.c7
-rw-r--r--gcc/tree-flow-inline.h12
-rw-r--r--gcc/tree-flow.h2
-rw-r--r--gcc/tree-inline.c4
-rw-r--r--gcc/tree-loop-distribution.c2
-rw-r--r--gcc/tree-mudflap.c8
-rw-r--r--gcc/tree-nested.c8
-rw-r--r--gcc/tree-object-size.c31
-rw-r--r--gcc/tree-pretty-print.c33
-rw-r--r--gcc/tree-profile.c11
-rw-r--r--gcc/tree-ssa-address.c62
-rw-r--r--gcc/tree-ssa-alias.c157
-rw-r--r--gcc/tree-ssa-alias.h6
-rw-r--r--gcc/tree-ssa-ccp.c43
-rw-r--r--gcc/tree-ssa-dce.c41
-rw-r--r--gcc/tree-ssa-dom.c30
-rw-r--r--gcc/tree-ssa-forwprop.c13
-rw-r--r--gcc/tree-ssa-loop-ivopts.c58
-rw-r--r--gcc/tree-ssa-loop-prefetch.c6
-rw-r--r--gcc/tree-ssa-math-opts.c22
-rw-r--r--gcc/tree-ssa-operands.c1
-rw-r--r--gcc/tree-ssa-pre.c3
-rw-r--r--gcc/tree-ssa-reassoc.c2
-rw-r--r--gcc/tree-ssa-sccvn.c157
-rw-r--r--gcc/tree-ssa-strlen.c47
-rw-r--r--gcc/tree-ssa-structalias.c108
-rw-r--r--gcc/tree-ssa-tail-merge.c52
-rw-r--r--gcc/tree-ssa.c8
-rw-r--r--gcc/tree-streamer-in.c2
-rw-r--r--gcc/tree-vect-generic.c318
-rw-r--r--gcc/tree-vect-patterns.c870
-rw-r--r--gcc/tree-vect-slp.c262
-rw-r--r--gcc/tree-vect-stmts.c134
-rw-r--r--gcc/tree-vectorizer.h4
-rw-r--r--gcc/tree-vrp.c36
-rw-r--r--gcc/tree.c49
-rw-r--r--gcc/tree.def37
-rw-r--r--gcc/tree.h107
-rw-r--r--gcc/var-tracking.c2150
-rw-r--r--gcc/varasm.c5
-rw-r--r--gcc/varpool.c6
-rw-r--r--gnattools/ChangeLog10
-rw-r--r--gnattools/Makefile.in34
-rw-r--r--libada/ChangeLog11
-rw-r--r--libada/Makefile.in12
-rwxr-xr-xlibada/configure7
-rw-r--r--libada/configure.ac6
-rw-r--r--libcpp/ChangeLog238
-rw-r--r--libcpp/directives.c20
-rw-r--r--libcpp/files.c5
-rw-r--r--libcpp/include/cpplib.h12
-rw-r--r--libcpp/include/line-map.h620
-rw-r--r--libcpp/init.c7
-rw-r--r--libcpp/internal.h131
-rw-r--r--libcpp/lex.c41
-rw-r--r--libcpp/line-map.c1074
-rw-r--r--libcpp/macro.c1381
-rw-r--r--libcpp/traditional.c2
-rw-r--r--libgcc/ChangeLog24
-rw-r--r--libgcc/config.host2
-rw-r--r--libgcc/config/alpha/linux-unwind.h2
-rw-r--r--libgcc/generic-morestack-thread.c3
-rw-r--r--libgcc/generic-morestack.c2
-rw-r--r--libgomp/ChangeLog4
-rw-r--r--libiberty/ChangeLog7
-rw-r--r--libiberty/cp-demangle.c24
-rw-r--r--libiberty/testsuite/demangle-expected5
-rw-r--r--libjava/ChangeLog7
-rw-r--r--libjava/include/dwarf2-signal.h15
-rw-r--r--libobjc/ChangeLog26
-rw-r--r--libobjc/class.c9
-rw-r--r--libobjc/init.c9
-rw-r--r--libobjc/sendmsg.c31
-rw-r--r--libstdc++-v3/ChangeLog201
-rw-r--r--libstdc++-v3/acinclude.m412
-rw-r--r--libstdc++-v3/config.h.in3
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver42
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/ctype_base.h64
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc243
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/ctype_inline.h75
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/error_constants.h142
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/os_defines.h68
-rwxr-xr-xlibstdc++-v3/configure9
-rw-r--r--libstdc++-v3/configure.host12
-rw-r--r--libstdc++-v3/doc/doxygen/user.cfg.in4
-rw-r--r--libstdc++-v3/include/Makefile.am125
-rw-r--r--libstdc++-v3/include/Makefile.in125
-rw-r--r--libstdc++-v3/include/bits/basic_string.h10
-rw-r--r--libstdc++-v3/include/bits/basic_string.tcc8
-rw-r--r--libstdc++-v3/include/bits/c++config2
-rw-r--r--libstdc++-v3/include/bits/codecvt.h4
-rw-r--r--libstdc++-v3/include/bits/hashtable.h42
-rw-r--r--libstdc++-v3/include/bits/list.tcc46
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h2
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h3
-rw-r--r--libstdc++-v3/include/bits/stl_list.h79
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h5
-rw-r--r--libstdc++-v3/include/bits/unordered_set.h28
-rw-r--r--libstdc++-v3/include/ext/alloc_traits.h13
-rw-r--r--libstdc++-v3/include/ext/pod_char_traits.h5
-rw-r--r--libstdc++-v3/include/tr2/bool_set320
-rw-r--r--libstdc++-v3/include/tr2/bool_set.tcc277
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset1472
-rw-r--r--libstdc++-v3/include/tr2/ratio59
-rw-r--r--libstdc++-v3/include/tr2/type_traits102
-rw-r--r--libstdc++-v3/libsupc++/cxxabi.h89
-rw-r--r--libstdc++-v3/libsupc++/del_op.cc5
-rw-r--r--libstdc++-v3/libsupc++/del_opnt.cc5
-rw-r--r--libstdc++-v3/libsupc++/del_opv.cc5
-rw-r--r--libstdc++-v3/libsupc++/del_opvnt.cc5
-rw-r--r--libstdc++-v3/libsupc++/eh_alloc.cc10
-rw-r--r--libstdc++-v3/libsupc++/eh_catch.cc6
-rw-r--r--libstdc++-v3/libsupc++/eh_globals.cc16
-rw-r--r--libstdc++-v3/libsupc++/eh_type.cc4
-rw-r--r--libstdc++-v3/libsupc++/new36
-rw-r--r--libstdc++-v3/libsupc++/new_op.cc2
-rw-r--r--libstdc++-v3/libsupc++/new_opnt.cc2
-rw-r--r--libstdc++-v3/libsupc++/new_opv.cc5
-rw-r--r--libstdc++-v3/libsupc++/new_opvnt.cc6
-rw-r--r--libstdc++-v3/libsupc++/pure.cc9
-rw-r--r--libstdc++-v3/libsupc++/unwind-cxx.h42
-rwxr-xr-xlibstdc++-v3/scripts/create_testsuite_files2
-rw-r--r--libstdc++-v3/testsuite/18_support/50594.cc72
-rw-r--r--libstdc++-v3/testsuite/20_util/bind/48698.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/pointer_traits/pointer_to.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc16
-rw-r--r--libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc95
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/allocator/minimal.cc45
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/requirements/base_classes.cc12
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc11
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc11
-rw-r--r--libstdc++-v3/testsuite/ext/codecvt/char-1.cc13
-rw-r--r--libstdc++-v3/testsuite/ext/codecvt/char-2.cc13
-rw-r--r--libstdc++-v3/testsuite/ext/codecvt/wchar_t.cc39
-rw-r--r--libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize_neg.cc5
-rw-r--r--libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/libstdc++-dg/conformance.exp1
-rw-r--r--libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc72
-rw-r--r--libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc32
-rw-r--r--libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc31
-rw-r--r--libstdc++-v3/testsuite/tr2/bases/value.cc97
-rw-r--r--libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc32
-rw-r--r--libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc31
-rw-r--r--libstdc++-v3/testsuite/tr2/direct_bases/value.cc91
-rw-r--r--libstdc++-v3/testsuite/tr2/headers/all.cc24
-rw-r--r--libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc26
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.cc1
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_allocator.h42
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_rvalref.h3
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_tr1.h9
966 files changed, 45575 insertions, 11750 deletions
diff --git a/contrib/ChangeLog.google-integration b/contrib/ChangeLog.google-integration
index b278e8c92c6..4063e04332b 100644
--- a/contrib/ChangeLog.google-integration
+++ b/contrib/ChangeLog.google-integration
@@ -1,3 +1,8 @@
+2011-10-23 Diego Novillo <dnovillo@google.com>
+
+ * testsuite-management/x86_64-unknown-linux-gnu.xfail: Update with
+ new/removed failures in trunk.
+
2011-10-02 Diego Novillo <dnovillo@google.com>
* testsuite-management/x86_64-unknown-linux-gnu.xfail: Update with
diff --git a/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail b/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail
index 1a2a5a5afec..27f49c8750f 100644
--- a/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail
+++ b/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail
@@ -1,23 +1,30 @@
# These tests fail in trunk in all configurations.
-FAIL: 23_containers/vector/requirements/dr438/assign_neg.cc (test for errors, line 1222)
+FAIL: 23_containers/vector/requirements/dr438/assign_neg.cc (test for errors, line 1223)
FAIL: 23_containers/vector/requirements/dr438/assign_neg.cc (test for excess errors)
FAIL: 23_containers/vector/requirements/dr438/constructor_1_neg.cc (test for excess errors)
-FAIL: 23_containers/vector/requirements/dr438/constructor_1_neg.cc (test for errors, line 1152)
+FAIL: 23_containers/vector/requirements/dr438/constructor_1_neg.cc (test for errors, line 1153)
FAIL: 23_containers/vector/requirements/dr438/constructor_2_neg.cc (test for excess errors)
-FAIL: 23_containers/vector/requirements/dr438/constructor_2_neg.cc (test for errors, line 1152)
+FAIL: 23_containers/vector/requirements/dr438/constructor_2_neg.cc (test for errors, line 1153)
FAIL: 23_containers/vector/requirements/dr438/insert_neg.cc (test for excess errors)
-FAIL: 23_containers/vector/requirements/dr438/insert_neg.cc (test for errors, line 1263)
+FAIL: 23_containers/vector/requirements/dr438/insert_neg.cc (test for errors, line 1264)
FAIL: gcc.dg/cproj-fails-with-broken-glibc.c execution test
XPASS: gcc.dg/inline_3.c (test for excess errors)
XPASS: gcc.dg/inline_4.c (test for excess errors)
FAIL: gcc.dg/tree-ssa/vrp47.c scan-tree-dump-times dom1 "x[^ ]* & y" 1
-XPASS: gcc.dg/uninit-B.c uninit i warning (test for warnings, line 12)
-XPASS: gcc.dg/uninit-pr19430.c uninitialized (test for warnings, line 41)
-XPASS: gcc.dg/uninit-pr19430.c (test for warnings, line 32)
XPASS: gcc.dg/unroll_2.c (test for excess errors)
XPASS: gcc.dg/unroll_3.c (test for excess errors)
XPASS: gcc.dg/unroll_4.c (test for excess errors)
FAIL: libmudflap.c++/pass55-frag.cxx ( -O) execution test
+FAIL: gcc.dg/torture/vector-shift2.c -O0 execution test
+XPASS: gcc.dg/vect/no-scevccp-outer-6-global.c scan-tree-dump-times vect "OUTER LOOP VECTORIZED." 1
+FAIL: gfortran.dg/select_type_12.f03 -O (test for excess errors)
+FAIL: gfortran.dg/select_type_12.f03 -O (internal compiler error)
+FAIL: gfortran.fortran-torture/execute/entry_4.f90 execution, -O2 -ftree-vectorize -msse2
+FAIL: gfortran.fortran-torture/execute/entry_4.f90 execution, -O2 -fomit-frame-pointer -finline-functions
+FAIL: gfortran.fortran-torture/execute/entry_4.f90 execution, -O3 -g
+FAIL: gfortran.fortran-torture/execute/entry_4.f90 execution, -O2 -fbounds-check
+FAIL: gfortran.fortran-torture/execute/entry_4.f90 execution, -O2
+FAIL: gfortran.fortran-torture/execute/entry_4.f90 execution, -O2 -fomit-frame-pointer -finline-functions -funroll-loops
# The following tests are failing with gold. The LTO plugin is not resolving
# names properly. Only builds configured to use gold will show these.
@@ -32,6 +39,33 @@ FAIL: boehm-gc.c/thread_leak_test.c -O2 (test for excess errors)
# This test fails in trunk with -m32 when compiled with -mtune=pentium4
FAIL: gcc.target/i386/pr27827.c scan-assembler fmul[ \t]*%st
+# These tests fail with -m32 -march=pentium3 on trunk
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50843
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O3 -g (internal compiler error)
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O2 (internal compiler error)
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O2 -flto -flto-partition=none
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O2 -flto
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -Os
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O3 -fomit-frame-pointer -funroll-loops (internal compiler error)
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O2 -flto (internal compiler error)
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O3 -g
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O3 -fomit-frame-pointer
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O3 -fomit-frame-pointer (internal compiler error)
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O2 -flto -flto-partition=none (internal compiler error)
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O1
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O2
+UNRESOLVED: gcc.c-torture/execute/vector-shift.c execution, -O3 -fomit-frame-pointer -funroll-loops
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O1 (internal compiler error)
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions (internal compiler error)
+FAIL: gcc.c-torture/execute/vector-shift.c compilation, -Os (internal compiler error)
+
+# These tests fail in trunk with -m32.
+FAIL: gcc.c-torture/execute/vector-shift2.c execution, -O0
+FAIL: gcc.c-torture/execute/vshuf-v16qi.c execution, -Os
+FAIL: gcc.c-torture/execute/vshuf-v2di.c execution, -Os
+FAIL: gcc.c-torture/execute/vshuf-v8hi.c execution, -Os
+
# These are flaky when tested in loaded machines (they exceed the timeout)
flaky | FAIL: libmudflap.cth/pass40-frag.c (-O2) output pattern test
flaky | FAIL: libmudflap.cth/pass40-frag.c (-static -DSTATIC) execution test
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4aa277aac4b..34e94e403fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,2451 @@
+2011-10-20 Dehao Chen <dehao@google.com>
+
+ * profile.c (compute_branch_probabilities): Compute and dump the
+ overlap between the static estimation and the instrumentation profile.
+ (OVERLAP_BASE): New macro.
+ (compute_frequency_overlap): New function
+
+2011-10-19 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (expand_vec_perm_vpshufb2_vpermq_even_odd): Use
+ d->op1 instead of d->op0 for the second vpshufb.
+ (expand_vec_perm_even_odd_1): For V8SImode fix vpshufd immediates.
+ (ix86_expand_vec_perm_const): If mask indicates two operands are
+ needed, but both are the same and expanding them as d.op0 == d.op1
+ failed, retry with d.op0 != d.op1.
+ (ix86_expand_vec_perm_builtin): Likewise. Handle sorry printing
+ also for d.nelt == 32.
+
+ PR middle-end/50754
+ * cfgexpand.c (expand_debug_expr): Handle WIDEN_LSHIFT_EXPR, ignore
+ VEC_PERM_EXPR.
+
+2011-10-19 Bernd Schmidt <bernds@codesourcery.com>
+
+ * regrename.h: New file.
+ * regrename.c: Include it. Also include "emit-rtl.h".
+ (struct du_head, struct du_chain, du_head_p DEF_VEC and
+ DEF_VEC_ALLOC_P): Move to regrename.h.
+ (do_replace): Remove declaration.
+ (insn_rr): New variable.
+ (cur_operand): New static variable.
+ (regrename_chain_from_id): Renamed from chain_from_id and no longer
+ static. All callers changed.
+ (record_operand_use): New static function.
+ (scan_rtx_reg): Use it.
+ (find_best_rename_reg): New function, broken out of rename_chains.
+ (rename_chains): Use it. Don't update chain regno and nregs here, ...
+ (regrename_do_replace): ... do it here instead. Renamed from
+ do_replace, and no longer static. All callers changed.
+ (regrename_analyze): No longer static. New arg bb_mask.
+ All callers changed. If bb_mask is nonzero, use it to limit the
+ number of basic blocks we analyze. If we failed to analyze a block,
+ clear insn operand data.
+ (record_out_operands): New arg insn_info. Update cur_operand if it is
+ nonnull.
+ (build_def_use): If insn_rr is nonnull, pass an insn_info to
+ record_out_operands, and update cur_operand here as well.
+ (regrename_init, regrename_finish): New functions.
+ (regrename_optimize): Use them.
+ * Makefile.in (regrename.o): Adjust dependencies.
+
+2011-10-19 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50769
+ * tree-ssa-tail-merge.c (replace_block_by): Calculate phi_vuse2
+ unconditionally. Handle case that phi_vuse2 is not an SSA_NAME. Add
+ dummy argument .MEM to phi when increasing number of arguments of phi by
+ redirecting edges to the block with phi.
+
+2011-10-19 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR bootstrap/50777
+ * configure.ac: Save and restore CXXFLAGS around
+ gcc_AC_CHECK_DECLS uses.
+ Check for madvise() declaration with g++ if --enable-build-with-cxx.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+ * ggc-page.c (USING_MADVISE): Also check HAVE_DECL_MADVISE.
+
+2011-10-19 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/49310
+ * var-tracking.c (loc_exp_dep, onepart_aux): New structs.
+ (variable_part): Replace offset with union.
+ (enum onepart_enum, onepart_enum_t): New.
+ (variable_def): Drop cur_loc_changed, add onepart.
+ (value_chain_def, const_value_chain): Remove.
+ (VAR_PART_OFFSET, VAR_LOC_1PAUX): New macros, with checking.
+ (VAR_LOC_DEP_LST, VAR_LOC_DEP_LSTP): New macros.
+ (VAR_LOC_FROM, VAR_LOC_DEPTH, VAR_LOC_DEP_VEC): Likewise.
+ (value_chain_pool, value_chains): Remove.
+ (dropped_values): New.
+ (struct parm_reg): Only if HAVE_window_save.
+ (vt_stack_adjustments): Don't record register arguments.
+ (dv_as_rtx): New.
+ (dv_onepart_p): Return a onepart_enum_t.
+ (onepart_pool): New.
+ (dv_pool): Remove.
+ (dv_from_rtx): New.
+ (variable_htab_free): Release onepart aux data. Reset flags.
+ (value_chain_htab_hash, value_chain_htab_eq): Remove.
+ (unshare_variable): Use onepart field. Propagate onepart aux
+ data or offset. Drop cur_loc_changed.
+ (val_store): Cope with NULL insn. Rephrase dump output. Check
+ for unsuitable locs. Add FIXME on using cselib locs.
+ (val_reset): Remove FIXME of unfounded concerns.
+ (val_resolve): Check for unsuitable locs. Add FIXME on using
+ cselib locs.
+ (variable_union): Use onepart field, adjust access to offset.
+ (NO_LOC_P): New.
+ (VALUE_CHANGED, DECL_CHANGED): Update doc.
+ (set_dv_changed): Clear NO_LOC_P when changed.
+ (find_loc_in_1pdv): Use onepart field.
+ (intersect_loc_chains): Likewise.
+ (unsuitable_loc): New.
+ (loc_cmp): Keep ENTRY_VALUEs at the end of the loc list.
+ (add_value_chain, add_value_chains): Remove.
+ (add_cselib_value_chains, remove_value_chain): Likewise.
+ (remove_value_chains, remove_cselib_value_chains): Likewise.
+ (canonicalize_loc_order_check): Use onepart. Drop cur_loc_changed.
+ (canonicalize_values_star, canonicalize_vars_star): Use onepart.
+ (variable_merge_over_cur): Likewise. Adjust access to offset.
+ Drop cur_loc_changed.
+ (variable_merge_over_src): Use onepart field.
+ (remove_duplicate_values): Likewise.
+ (variable_post_merge_new_vals): Likewise.
+ (find_mem_expr_in_1pdv): Likewise.
+ (dataflow_set_preserve_mem_locs): Likewise. Drop cur_loc_changed
+ and value chains.
+ (dataflow_set_remove_mem_locs): Likewise. Use VAR_LOC_FROM.
+ (variable_different_p): Use onepart field. Move onepart test out
+ of the loop.
+ (argument_reg_set): Drop.
+ (add_uses, add_stores): Preserve but do not record in dynamic
+ tables equivalences for ENTRY_VALUEs and CFA_based addresses.
+ Avoid unsuitable address expressions.
+ (EXPR_DEPTH): Unlimit.
+ (EXPR_USE_DEPTH): Repurpose PARAM_MAX_VARTRACK_EXPR_DEPTH.
+ (prepare_call_arguments): Use DECL_RTL_IF_SET.
+ (dump_var): Adjust access to offset.
+ (variable_from_dropped, recover_dropped_1paux): New.
+ (variable_was_changed): Drop cur_loc_changed. Use onepart.
+ Preserve onepart aux in empty_var. Recover empty_var and onepart
+ aux from dropped_values.
+ (find_variable_location_part): Special-case onepart. Adjust
+ access to offset.
+ (set_slot_part): Use onepart. Drop cur_loc_changed. Adjust
+ access to offset. Initialize onepaux. Drop value chains.
+ (delete_slot_part): Drop value chains. Use VAR_LOC_FROM.
+ (VEC (variable, heap), VEC (rtx, stack)): Define.
+ (expand_loc_callback_data): Drop dummy, cur_loc_changed,
+ ignore_cur_loc. Add expanding, pending, depth.
+ (loc_exp_dep_alloc, loc_exp_dep_clear): New.
+ (loc_exp_dep_insert, loc_exp_dep_set): New.
+ (notify_dependents_of_resolved_value): New.
+ (update_depth, vt_expand_var_loc_chain): New.
+ (vt_expand_loc_callback): Revamped.
+ (resolve_expansions_pending_recursion): New.
+ (INIT_ELCD, FINI_ELCD): New.
+ (vt_expand_loc): Use the new macros above. Drop ignore_cur_loc
+ parameter, adjust all callers.
+ (vt_expand_loc_dummy): Drop.
+ (vt_expand_1pvar): New.
+ (emit_note_insn_var_location): Operate on non-debug decls only.
+ Revamp multi-part cur_loc recomputation and one-part expansion.
+ Drop cur_loc_changed. Adjust access to offset.
+ (VEC (variable, heap)): Drop.
+ (changed_variables_stack, changed_values_stack): Drop.
+ (check_changed_vars_0, check_changed_vars_1): Remove.
+ (check_changed_vars_2, check_changed_vars_3): Remove.
+ (values_to_stack, remove_value_from_changed_variables): New.
+ (notify_dependents_of_changed_value, process_changed_values): New.
+ (emit_notes_for_changes): Revamp onepart updates.
+ (emit_notes_for_differences_1): Use onepart. Drop cur_loc_changed
+ and value chains. Propagate onepaux. Recover empty_var and onepaux
+ from dropped_values.
+ (emit_notes_for_differences_2): Drop value chains.
+ (emit_notes_in_bb): Adjust.
+ (vt_emit_notes): Drop value chains, changed_variables_stack.
+ Initialize and release dropped_values.
+ (create_entry_value): Revamp.
+ (vt_add_function_parameter): Use new interface.
+ (note_register_arguments): Remove.
+ (vt_initialize): Drop value chains and register arguments.
+ (vt_finalize): Drop value chains. Release windowed_parm_regs only
+ if HAVE_window_save.
+ * rtl.h: Document various pass-local uses of RTL flags.
+ * tree.h (DECL_RTL_KNOWN_SET): New.
+ * doc/invoke.texi (param max-vartrack-expr-depth): Update
+ description and default.
+
+2011-10-19 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50447
+ * config/avr/avr.md (cc): New alternative out_plus_noclobber.
+ (adjust_len): Ditto.
+ (addhi3): Don't pipe through short; use gen_int_mode instead.
+ Prior to reload, expand to gen_addhi3_clobber.
+ (*addhi3): Use avr_out_plus_noclobber if applicable, use
+ out_plus_noclobber in cc and adjust_len attribute.
+ (addhi3_clobber): 2 new RTL peepholes.
+ (addhi3_clobber): New insn.
+ * config/avr/avr-protos.h: (avr_out_plus_noclobber): New prototype.
+ * config/avr/avr.c (avr_out_plus_noclobber): New function.
+ (notice_update_cc): Handle CC_OUT_PLUS_NOCLOBBER.
+ (avr_out_plus_1): Tweak if only MSB is +/-1 and other bytes are 0.
+ Set cc0 to set_zn for adiw on 16-bit values.
+ (adjust_insn_length): Handle ADJUST_LEN_OUT_PLUS_NOCLOBBER.
+ (expand_epilogue): No need to add 0 to frame_pointer_rtx.
+
+2011-10-19 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50780
+ * tree-ssa-forwprop.c (forward_propagate_into_cond): Verify
+ the condition is properly gimple before using it.
+ * tree-eh (stmt_could_throw_1_p): Properly extract the
+ operation type from comparisons.
+
+2011-10-19 Roland Stigge <stigge@antcom.de>
+
+ PR translation/48638
+ * plugin.c (add_new_plugin): Fix typo in fatal_error message.
+
+2011-10-19 Roland Stigge <stigge@antcom.de>
+
+ PR translation/49517
+ * config/rx/rx.c (rx_print_operand): Fix typo in warning message.
+
+2011-10-19 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50768
+ * gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite.
+
+2011-10-19 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/50340
+ * sel-sched-ir.c (update_target_availability): LHS register
+ availability is not known if the unavailable LHS of the other
+ expression is a different register.
+
+2011-10-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ PR target/50310
+ * config/spu/spu.c (spu_emit_vector_compare): Support unordered
+ floating-point comparisons.
+
+2011-10-19 Jan Hubicka <jh@suse.cz>
+
+ * cgraphunit.c (handle_alias_pairs): Also handle wekref with destination
+ declared.
+ (output_weakrefs): New function.
+ * varpool.c (varpool_create_variable_alias): Handle external aliases.
+
+2011-10-19 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (loc_descriptor): For SUBREG pass SUBREG_REG's mode as
+ second argument instead of mode.
+
+2011-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_vec_perm): In merge_two use
+ mode SUBREG of operands[0] as target.
+ (valid_perm_using_mode_p): Don't ignore higher bits of d->perm.
+ (expand_vec_pshufb): For V8SImode vmode emit avx2_permvarv8si.
+ (expand_vec_perm_1): Handle identity and some broadcast
+ permutations.
+ (expand_vec_perm_interleave2): Handle also 32-byte modes, using
+ vperm2[fi]128 or vpunpck[lh]* followed by single insn permutation.
+ For d->testing_p return true earlier to avoid creating more GC
+ garbage.
+ (expand_vec_perm_vpermq_perm_1): New function.
+ (expand_vec_perm_vpshufb2_vpermq): For d->testing_p return true
+ earlier to avoid creating more GC garbage. Fix handling of
+ V16HImode. Avoid some SUBREGs in SET_DEST.
+ (expand_vec_perm_broadcast_1): Return false for 32-byte integer
+ vector modes.
+ (expand_vec_perm_vpshufb4_vpermq2): New function.
+ (ix86_expand_vec_perm_builtin_1): Call expand_vec_perm_vpermq_perm_1
+ and expand_vec_perm_vpshufb4_vpermq2.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/arm/driver-arm.c (host_detect_local_cpu): Close the file
+ before exiting.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ PR tree-optimization/50717
+
+ * tree-ssa-math-opts.c (is_widening_mult_p): Remove the 'type'
+ parameter. Calculate 'type' from stmt.
+ (convert_mult_to_widen): Update call the is_widening_mult_p.
+ (convert_plusminus_to_widen): Likewise.
+
+2011-10-18 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/spu/spu.c (struct machine_function): New data structure.
+ (spu_init_machine_status): New function.
+ (spu_option_override): Install it.
+ (get_pic_reg): Set and use cfun->machine->pic_reg.
+ (spu_split_immediate): Do not set crtl->uses_pic_offset_table.
+ (need_to_save_reg): Use cfun->machine->pic_reg instead of
+ checking crtl->uses_pic_offset_table.
+ (spu_expand_prologue): Likewise.
+
+2011-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50735
+ * function.c (gimplify_parameters): Use create_tmp_var instead of
+ create_tmp_reg. If parm is not TREE_ADDRESSABLE and type is complex
+ or vector type, set DECL_GIMPLE_REG_P.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ * config.host (arm*-*-linux*): Add driver-arm.o and x-arm.
+ * config/arm/arm.opt: Add 'native' processor_type and
+ arm_arch enum values.
+ * config/arm/arm.h (host_detect_local_cpu): New prototype.
+ (EXTRA_SPEC_FUNCTIONS): New define.
+ (MCPU_MTUNE_NATIVE_SPECS): New define.
+ (DRIVER_SELF_SPECS): New define.
+ * config/arm/driver-arm.c: New file.
+ * config/arm/x-arm: New file.
+ * doc/invoke.texi (ARM Options): Document -mcpu=native,
+ -mtune=native and -march=native.
+
+2011-10-18 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/50205
+ * sel-sched.c (count_occurrences_1): Simplify on the assumption that
+ p->x is a register. Forbid substitution when the same register is
+ found in a different mode.
+ (count_occurrences_equiv): Assert that 'what' is a register.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50767
+ * tree-ssa-pre.c (create_expression_by_pieces): Update the
+ folded statement.
+
+2011-10-18 Julian Brown <julian@codesourcery.com>
+
+ * config/arm/arm.c (arm_block_move_unaligned_straight)
+ (arm_adjust_block_mem, arm_block_move_unaligned_loop)
+ (arm_movmemqi_unaligned): New.
+ (arm_gen_movmemqi): Support unaligned block copies.
+
+2011-10-18 Ira Rosen <ira.rosen@linaro.org>
+
+ * doc/md.texi (vec_widen_ushiftl_hi, vec_widen_ushiftl_lo,
+ vec_widen_sshiftl_hi, vec_widen_sshiftl_lo): Document.
+ * tree-pretty-print.c (dump_generic_node): Handle WIDEN_LSHIFT_EXPR,
+ VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
+ (op_code_prio): Likewise.
+ (op_symbol_code): Handle WIDEN_LSHIFT_EXPR.
+ * optabs.c (optab_for_tree_code): Handle
+ VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
+ (init-optabs): Initialize optab codes for vec_widen_u/sshiftl_hi/lo.
+ * optabs.h (enum optab_index): Add OTI_vec_widen_u/sshiftl_hi/lo.
+ * genopinit.c (optabs): Initialize the new optabs.
+ * expr.c (expand_expr_real_2): Handle
+ VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
+ * gimple-pretty-print.c (dump_binary_rhs): Likewise.
+ * tree-vectorizer.h (NUM_PATTERNS): Increase to 8.
+ * tree.def (WIDEN_LSHIFT_EXPR, VEC_WIDEN_LSHIFT_HI_EXPR,
+ VEC_WIDEN_LSHIFT_LO_EXPR): New.
+ * cfgexpand.c (expand_debug_expr): Handle new tree codes.
+ * tree-vect-patterns.c (vect_vect_recog_func_ptrs): Add
+ vect_recog_widen_shift_pattern.
+ (vect_handle_widen_mult_by_const): Rename...
+ (vect_handle_widen_op_by_const): ...to this. Handle shifts.
+ Add a new argument, update documentation.
+ (vect_recog_widen_mult_pattern): Assume that only second
+ operand can be constant. Update call to
+ vect_handle_widen_op_by_const.
+ (vect_recog_over_widening_pattern): Fix typo.
+ (vect_recog_widen_shift_pattern): New.
+ * tree-vect-stmts.c (vectorizable_type_promotion): Handle
+ widening shifts.
+ (supportable_widening_operation): Likewise.
+ * tree-inline.c (estimate_operator_cost): Handle new tree codes.
+ * tree-vect-generic.c (expand_vector_operations_1): Likewise.
+ * tree-cfg.c (verify_gimple_assign_binary): Likewise.
+ * config/arm/neon.md (neon_vec_<US>shiftl_<mode>): New.
+ (vec_widen_<US>shiftl_lo_<mode>, neon_vec_<US>shiftl_hi_<mode>,
+ vec_widen_<US>shiftl_hi_<mode>, neon_vec_<US>shift_left_<mode>):
+ Likewise.
+ * config/arm/predicates.md (const_neon_scalar_shift_amount_operand):
+ New.
+ * config/arm/iterators.md (V_innermode): New.
+ * tree-vect-slp.c (vect_build_slp_tree): Require same shift operand
+ for widening shift.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-alias.h (struct pt_solution): Remove
+ vars_contains_restrict member.
+ (pt_solutions_same_restrict_base): Remove.
+ (pt_solution_set): Adjust.
+ * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Remove
+ vars_contains_restrict handling.
+ (dump_points_to_solution): Likewise.
+ (ptr_derefs_may_alias_p): Do not call pt_solutions_same_restrict_base.
+ * tree-ssa-structalias.c (struct variable_info): Remove is_restrict_var
+ field.
+ (new_var_info): Do not initialize it.
+ (ipa_escaped_pt): Adjust.
+ (make_constraint_from_restrict): Make the tag global.
+ (make_constraint_from_global_restrict): New function.
+ (make_constraint_from_heapvar): Remove.
+ (create_variable_info_for): Do not make restrict vars point
+ to NONLOCAL.
+ (intra_create_variable_infos): Likewise.
+ (find_what_var_points_to): Remove vars_contains_restrict handling.
+ (pt_solution_set): Adjust.
+ (pt_solution_ior_into): Likewise.
+ (pt_solutions_same_restrict_base): Remove.
+ (compute_points_to_sets): Do not test is_restrict_var.
+ * cfgexpand.c (update_alias_info_with_stack_vars): Adjust.
+ * gimple-pretty-print.c (pp_points_to_solution): Likewise.
+
+2011-10-18 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50672
+ * tree-ssa-dce.c (mark_virtual_operand_for_renaming): New function,
+ factored out of ...
+ (mark_virtual_phi_result_for_renaming): Use
+ mark_virtual_operand_for_renaming.
+ * tree-flow.h (mark_virtual_operand_for_renaming): Declare.
+ * tree-ssa-tail-merge.c (release_last_vdef): New function.
+ (purge_bbs): Add update_vops parameter. Call release_last_vdef for each
+ deleted basic block.
+ (tail_merge_optimize): Add argument to call to purge_bbs.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50716
+ * expr.c (get_object_or_type_alignment): New function.
+ (expand_assignment): Use it.
+ (expand_expr_real_1): Likewise.
+
+2011-10-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50760
+ * input.c (dump_line_table_statistics): Use long, not size_t.
+
+2011-10-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc.md (in_call_delay): Fix formatting issues.
+
+2011-10-17 Simon Baldwin <simonb@google.com>
+ Ian Lance Taylor <iant@google.com>
+
+ * configure.ac: Add --with-native-system-header-dir. Set and
+ substitute NATIVE_SYSTEM_HEADER_DIR. Use native_system_header
+ when setting target_header_dir.
+ * config.gcc: Always set native_system_header_dir.
+ (*-*-gnu*): Set native_system_header_dir. Don't use t-gnu.
+ (i[34567]86-pc-msdosdjgpp*): Set native_system_header_dir. Don't
+ use i386/t-djgpp.
+ (i[34567]86-*-mingw* | x86_64-*-mingw*): Set
+ native_system_header_dir.
+ (spu-*-elf*): Set native_system_header_dir.
+ * Makefile.in (NATIVE_SYSTEM_HEADER_DIR): Set to
+ @NATIVE_SYSTEM_HEADER_DIR@.
+ (PREPROCESSOR_DEFINES): Define NATIVE_SYSTEM_HEADER_DIR.
+ * cppdefault.c (STANDARD_INCLUDE_DIR): Don't define.
+ (NATIVE_SYSTEM_HEADER_COMPONENT): Rename from
+ STANDARD_INCLUDE_COMPONENT.
+ (cpp_include_defaults): Don't use SYSTEM_INCLUDE_DIR. Rename
+ STANDARD_INCLUDE_DIR to NATIVE_SYSTEM_HEADER_DIR.
+ * system.h: Poison SYSTEM_INCLUDE_DIR, STANDARD_INCLUDE_DIR, and
+ STANDARD_INCLUDE_COMPONENT.
+ * config/i386/t-mingw32 (NATIVE_SYSTEM_HEADER_DIR): Remove.
+ * config/i386/t-mingw-w32: Likewise.
+ * config/i386/t-mingw-w64: Likewise.
+ * config/spu/t-spu-elf: Likewise.
+ * config/i386/t-djgpp: Remove.
+ * config/t-gnu: Remove.
+ * config/i386/mingw32.h (STANDARD_INCLUDE_DIR): Don't define.
+ (NATIVE_SYSTEM_HEADER_COMPONENT): Rename from
+ STANDARD_INCLUDE_COMPONENT.
+ * config/i386/djgpp.h (STANDARD_INCLUDE_DIR): Don't define.
+ * config/spu/spu-elf.h: Likewise.
+ * config/vms/xm-vms.h: Likewise.
+ * config/gnu.h: Likewise.
+ * config/openbsd.h (INCLUDE_DEFAULTS): Change STANDARD_INCLUDE_DIR
+ and STANDARD_INCLUDE_COMPONENT to NATIVE_SYSTEM_HEADER_DIR and
+ NATIVE_SYSTME_HEADER_COMPONENT.
+ * doc/install.texi (Configuration): Document
+ --with-native-system-header-dir. Mention it in the documentation
+ for --with-sysroot and --with-build-sysroot.
+ * doc/tm.texi.in (Driver): Don't document SYSTEM_INCLUDE_DIR or
+ STANDARD_INCLUDE_DIR. Rename STANDARD_INCLUDE_COMPONENT to
+ NATIVE_SYSTEM_HEADER_COMPONENT. Rename uses of
+ STANDARD_INCLUDE_DIR to NATIVE_SYSTEM_HEADER_DIR.
+ * doc/fragments.texi (Target Fragment): Don't document
+ NATIVE_SYSTEM_HEADER_DIR.
+ * configure, doc/tm.texi: Rebuild.
+
+2011-10-17 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.md: Use register_or_zero_operand where rJ
+ is the constraint.
+
+ * config/sparc/sparc.md (vec_perm_constv8qi, vec_perm<mode>): New
+ patterns.
+ * config/sparc/sparc.c (sparc_expand_vec_perm_bmask): New function.
+ * config/sparc/sparc-protos.h (sparc_expand_vec_perm_bmask): Declare.
+
+2011-10-17 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc-modes.def: Add single entry vector modes for
+ DImode and SImode.
+ * config/sparc/sparc.md (V32, V32I, V64, V64I, V64N8): Delete
+ mode iterators.
+ (mov<V32:mode>): Revert back to plain SFmode pattern.
+ (*movsf_insn): Likewise.
+ (mov<V64:mode>): Revert back to plain DFmode pattern.
+ (*movdf_insn_sp32): Likewise.
+ (*movdf_insn_sp32_v9): Likewise.
+ (*movdf_insn_sp64): Likewise.
+ (V64 mode splitters) Likewise.
+ (addsi3): Remove VIS alternatives.
+ (subsi3): Likewise.
+ (and<V64I:mode>3): Revert to DImode only pattern.
+ (and<V64I:mode>3_sp32): Likewise.
+ (*and<V64I:mode>3_sp64): Likewise.
+ (and<V32I:mode>3): Likewise.
+ (*and_not_<V64I:mode>_sp32): Likewise.
+ (*and_not_<V64I:mode>_sp64): Likewise.
+ (*and_not_<V32I:mode>): Likewise.
+ (ior<V64I:mode>3): Likewise.
+ (*ior<V64I:mode>3_sp32): Likewise.
+ (*ior<V64I:mode>3_sp64): Likewise.
+ (ior<V32I:mode>3): Likewise.
+ (*or_not_<V64I:mode>_sp32): Likewise.
+ (*or_not_<V64I:mode>_sp64): Likewise.
+ (*or_not_<V32I:mode>): Likewise.
+ (xor<V64I:mode>3): Likewise.
+ (*xor<V64I:mode>3_sp32): Likewise.
+ (*xor<V64I:mode>3_sp64): Likewise.
+ (xor<V32I:mode>3): Likewise.
+ (V64I mode splitters): Likewise.
+ (*xor_not_<V64I:mode>_sp32): Likewise.
+ (*xor_not_<V64I:mode>_sp64): Likewise.
+ (*xor_not_<V32I:mode>): Likewise.
+ (one_cmpl<V64I:mode>2): Likewise.
+ (*one_cmpl<V64I:mode>2_sp32): Likewise.
+ (*one_cmpl<V64I:mode>2_sp64): Likewise.
+ (one_cmpl<V32I:mode>2): Likewise.
+ (VM32, VM64, VMALL): New mode iterators.
+ (vbits, vconstr, vfptype): New mode attributes.
+ (mov<VMALL:mode>): New expander.
+ (*mov<VM32:mode>_insn): New insn.
+ (*mov<VM64:mode>_insn_sp64): New insn.
+ (*mov<VM64:mode>_insn_sp32): New insn, and associated splitter
+ specifically for the register to memory case.
+ (vec_init<mode>): New expander.
+ (VADDSUB): New mode iterator.
+ (<plusminus_insn>v2si3, <plusminus_insn>v2hi3): Remove and replace
+ with...
+ (<plusminus_insn><mode>3): New consolidated pattern.
+ (VL): New mode iterator for logical operations.
+ (vlsuf): New more attribute.
+ (vlop): New code iterator.
+ (vlinsn, vlninsn): New code attributes.
+ (<code><mode>3): New insn to non-negated vector logical ops.
+ (*not_<code><mode>3): Likewise for negated variants.
+ (*nand<mode>_vis): New insn.
+ (vlnotop): New code iterator.
+ (*<code>_not1<mode>_vis, *<code>_not2<mode>_vis): New insns.
+ (one_cmpl<mode>2): New insn.
+ (faligndata<V64I:mode>_vis): Rewrite to use VM64 iterator.
+ (bshuffle<VM64:mode>_vis): Likewise.
+ (v<vis3_shift_patname><mode>3): Use GCM mode iterator.
+ (fp<plusminus_insn>64_vis): Use V1DI mode.
+ (VASS mode iterator): Use V1SI not SI mode.
+ * config/sparc/sparc.c (sparc_vis_init_builtins): Account for
+ single-entry vector mode changes.
+ (sparc_expand_builtin): Likewise.
+ (sparc_expand_vector_init): New function.
+ * config/sparc/sparc-protos.h (sparc_expand_vector_init): Declare.
+
+2011-10-17 Kai Tietz <ktietz@redhat.com>
+
+ * fold-const.c (simple_operand_p_2): New function.
+ (fold_truthop): Rename to
+ (fold_truth_andor_1): function name.
+ Additionally remove branching creation for logical and/or.
+ (fold_truth_andor): Handle branching creation for logical and/or here.
+
+2011-10-17 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page.c (USING_MADVISE): Adjust ifdef to check for USING_MMAP.
+
+2011-10-17 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.h (ASSEMBLER_DIALECT): Remove.
+ * config/avr/avr.md (mcu_have_movw, mcu_mega): Remove attributes.
+ (adjust_len): Add alternative "call".
+ (isa, enabled): New insn attributes.
+ (length): Use match_test with AVR_HAVE_JMP_CALL instead of
+ mcu_mega attribute.
+ (*sbrx_branch<mode>): Ditto.
+ (*sbrx_and_branch<mode>): Ditto.
+ (*sbix_branch): Ditto.
+ (*sbix_branch_bit7): Ditto.
+ (*sbix_branch_tmp): Ditto.
+ (*sbix_branch_tmp_bit7): Ditto.
+ (jump): Ditto.
+ (negsi2): Use attribute "isa" instead of assembler dialect.
+ (extendhisi2): Ditto.
+ (call_insn, call_value_insn): Set adjust_len attribute.
+ (indirect_jump): Indent to coding rules.
+ (call_prologue_saves): Use isa attribute instead of mcu_mega.
+ (epilogue_restores): Ditto. Fix setting of SP as described in the
+ RTX pattern.
+ (*indirect_jump): Fusion of *jcindirect_jump, *njcindirect_jump
+ and *indirect_jump_avr6.
+ (*tablejump): Fusion of *tablejump_rjmp and *tablejump_lib.
+ (*jcindirect_jump, *njcindirect_jump, *indirect_jump_avr6): Remove.
+ (*tablejump_rjmp, *tablejump_lib): Remove.
+ * config/avr/avr.c (adjust_insn_length): Handle ADJUST_LEN_CALL.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50757
+ * doc/invoke.texi ([Wnonnull]): Update.
+
+2011-10-17 Richard Henderson <rth@redhat.com>
+
+ PR 50746
+ * optabs.c (expand_vec_perm_expr): Fix indexing error.
+
+2011-10-17 Sergio Durigan Junior <sergiodj@redhat.com>
+
+ * configure.ac: Display `yes' if the SystemTap header has been
+ found.
+ * configure: Regenerate.
+
+2011-10-08 Andi Kleen <ak@linux.intel.com>
+
+ PR other/50636
+ * config.in, configure: Regenerate.
+ * configure.ac (madvise): Add to AC_CHECK_FUNCS.
+ * ggc-page.c (USING_MADVISE): Add.
+ (page_entry): Add discarded field.
+ (alloc_page): Check for discarded pages.
+ (release_pages): Add USING_MADVISE branch.
+
+2011-10-17 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50729
+ * tree-vrp.c (extract_range_from_unary_expr_1): Remove
+ redundant test.
+ (simplify_conversion_using_ranges): Properly test the
+ intermediate result.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * ggc.h (ggc_round_alloc_size): Declare new public entry point.
+ * ggc-none.c (ggc_round_alloc_size): New public stub function.
+ * ggc-page.c (ggc_alloced_size_order_for_request): New static
+ function. Factorized from ggc_internal_alloc_stat.
+ (ggc_round_alloc_size): New public function. Uses
+ ggc_alloced_size_order_for_request.
+ (ggc_internal_alloc_stat): Use ggc_alloced_size_order_for_request.
+ * ggc-zone.c (ggc_round_alloc_size): New public function extracted
+ from ggc_internal_alloc_zone_stat.
+ (ggc_internal_alloc_zone_stat): Use ggc_round_alloc_size.
+ * toplev.c (general_init): Initialize
+ line_table->alloced_size_for_request.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * input.c (ONE_K, ONE_M, SCALE, STAT_LABEL, FORMAT_AMOUNT): New
+ macros.
+ (num_expanded_macros_counter, num_macro_tokens_counter): Declare
+ new counters.
+ (dump_line_table_statistics): Define new function.
+ * input.h (dump_line_table_statistics): Declare new function.
+ * toplev.c (dump_memory_report): Call dump_line_table_statistics.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * doc/cppopts.texi: Document -fdebug-cpp.
+ * doc/invoke.texi: Add -fdebug-cpp to the list of preprocessor
+ options.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc/diagnostic.h (diagnostic_report_current_module): Add a
+ location parameter.
+ * diagnostic.c (diagnostic_report_current_module): Add a location
+ parameter to the function definition. Use it instead of
+ input_location. Resolve the virtual location rather than just
+ looking up its map and risking to touch a resulting macro map.
+ (default_diagnostic_starter): Pass the relevant diagnostic
+ location to diagnostic_report_current_module.
+ * tree-diagnostic.c (maybe_unwind_expanded_macro_loc): New.
+ (virt_loc_aware_diagnostic_finalizer): Likewise.
+ (diagnostic_report_current_function): Pass the
+ relevant location to diagnostic_report_current_module.
+ * tree-diagnostic.h (virt_loc_aware_diagnostic_finalizer): Declare
+ new function.
+ * toplev.c (general_init): By default, use the new
+ virt_loc_aware_diagnostic_finalizer as diagnostic finalizer.
+ * Makefile.in: Add vec.h dependency to tree-diagnostic.c.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * doc/cppopts.texi (-ftrack-macro-expansion): Document new option.
+ * doc/invoke.texi (-ftrack-macro-expansion): Add this to the list of
+ preprocessor related options.
+
+2011-10-15 Tom Tromey <tromey@redhat>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * input.h (struct expanded_location): Move to libcpp/line-map.h.
+ (LOCATION_COLUMN): New accessor
+ (in_system_header_at): Use linemap_location_in_system_header_p.
+ * diagnostic.c (diagnostic_report_current_module): Adjust to avoid
+ touching the internals of struct line_map. Use the public API.
+ instead.
+ (diagnostic_report_diagnostic): Don't use relational operator '<'
+ on virtual locations. Use linemap_location_before_p instead.
+ * input.c (expand_location): Adjust to expand to the tokens'
+ spelling location when macro location tracking is on.
+
+
+2011-10-08 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page.c (GGC_QUIRE_SIZE): Increase to 512
+
+2011-10-13 Andi Kleen <ak@linux.intel.com>
+
+ * toplev.c (compile_file): Rename __gnu_slim_lto to __gnu_lto_slim.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50727
+ * tree-vect-patterns.c (vect_operation_fits_smaller_type): Add
+ DEF_STMT to the list of statements to be replaced by the
+ pattern statements.
+
+2011-10-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/50615
+ * combine.c (distribute_notes) <REG_ARGS_SIZE>: Skip if I3 is a no-op.
+
+2011-10-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * tree-vectorizer.h (NUM_PATTERNS): Increase to 7.
+ * tree-vect-patterns.c (vect_vect_recog_func_ptrs): Add
+ vect_recog_bool_pattern.
+ (check_bool_pattern, adjust_bool_pattern_cast,
+ adjust_bool_pattern, vect_recog_bool_pattern): New functions.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ * tree-vect-stmts.c (vectorizable_load): For SLP without permutation
+ treat the first load of the node as the first element in its
+ interleaving chain.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Swap the operands if
+ necessary and possible.
+ (vect_build_slp_tree): Add new argument. Allow load groups of any size
+ in basic blocks. Keep all the loads for further permutation check.
+ Use the new argument to determine if there is a permutation. Update
+ the recursive calls.
+ (vect_supported_load_permutation_p): Allow subchains of interleaving
+ chains in basic block vectorization.
+ (vect_analyze_slp_instance): Update the call to vect_build_slp_tree.
+ Check load permutation based on the new parameter.
+ (vect_schedule_slp_instance): Don't start from the first element in
+ interleaving chain unless the loads are permuted.
+
+2011-10-15 Jan Hubicka <jh@suse.cz>
+
+ PR target/48668
+ PR target/50689
+ * cgraphunit.c (cgraph_expand_function): Expand thunks and alises
+ after function body.
+
+2011-10-15 Richard Henderson <rth@redhat.com>
+
+ * tree-vect-slp.c: Include langhooks.h.
+ (vect_create_mask_and_perm): Emit VEC_PERM_EXPR, not a builtin.
+ (vect_transform_slp_perm_load): Use can_vec_perm_expr_p. Simplify
+ mask creation for VEC_PERM_EXPR.
+ * tree-vect-stmts.c (perm_mask_for_reverse): Return the mask,
+ not the builtin.
+ (reverse_vec_elements): Emit VEC_PERM_EXPR not a builtin.
+ * Makefile.in (tree-vect-slp.o): Update dependency.
+ * optabs.c (can_vec_perm_expr_p): Allow NULL as unknown constant.
+
+2011-10-15 Alan Modra <amodra@gmail.com>
+
+ PR bootstrap/50738
+ * ifcvt.c (dead_or_predicable): Revert accidental commit with
+ HAVE_simple_return test.
+
+2011-10-15 Alan Modra <amodra@gmail.com>
+
+ * ifcvt.c (dead_or_predicable): Disable if-conversion when
+ doing so is likely to kill a shrink-wrapping opportunity.
+
+ PR rtl-optimization/49941
+ * jump.c (mark_jump_label_1): Set JUMP_LABEL for simple_return jumps.
+
+ * rtl.h (set_return_jump_label): Declare.
+ * function.c (set_return_jump_label): New function, extracted..
+ (thread_prologue_and_epilogue_insns): ..from here. Use it in
+ another instance to set return jump_label.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Use set_return_jump_label.
+ * reorg.c (find_end_label): Likewise.
+
+2011-10-14 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sol2.h: Protect -m{cpu,tune}=native handling
+ with a more complete cpp test.
+ * config/sparc/linux64.h: Likewise.
+ * config/sparc/linux.h: Likewise.
+ * config/sparc/sparc.opt (sparc_debug): New target variable.
+ (mdebug): New target option.
+ * config/sparc/sparc.h (MASK_DEBUG_OPTIONS, MASK_DEBUG_ALL,
+ TARGET_DEBUG_OPTIONS): New defines.
+ * config/sparc/sparc.c (debug_target_flag_bits,
+ debug_target_flags): New functions.
+ (sparc_option_override): Add name strings back to cpu_table[].
+ Parse -mdebug string. When TARGET_DEBUG_OPTIONS is true, print
+ out the target flags before and after override processing as well
+ as the selected cpu. If MASK_V8PLUS, make sure that the selected
+ cpu is at least v9.
+
+2011-10-15 Oleg Endo <oleg.endo@t-online.de>
+
+ PR target/49263
+ * config/sh/sh.h (ZERO_EXTRACT_ANDMASK): New macro.
+ * config/sh/sh.c (sh_rtx_costs): Add test instruction case.
+ * config/sh/sh.md (tstsi_t): Name existing insn. Make inner
+ and instruction commutative.
+ (tsthi_t, tstqi_t, tstqi_t_zero, tstsi_t_and_not,
+ tstsi_t_zero_extract_eq, tstsi_t_zero_extract_xor,
+ tstsi_t_zero_extract_subreg_xor_little,
+ tstsi_t_zero_extract_subreg_xor_big): New insns.
+ (*movsicc_t_false, *movsicc_t_true): Replace space with tab in
+ asm output.
+ (*andsi_compact): Reorder alternatives so that K08 is considered first.
+
+2011-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50354
+ * config/sparc/linux64.h (TARGET_DEFAULT): Only override if the default
+ processor is at least V9 and TARGET_64BIT_DEFAULT is defined.
+
+2011-10-14 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * invoke.texi (AVR Options): Avoid \leq{}.
+
+2011-10-14 Kai Tietz <ktietz@redhat.com>
+
+ * gimplify.c (gimplify_expr): Take care that for bitwise-binary
+ transformation the operands have compatible types.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_widen_smult_hi_v8hi,
+ vec_widen_smult_lo_v8hi, vec_widen_umult_hi_v8hi,
+ vec_widen_umult_lo_v8hi): Macroize using VI2_AVX2
+ mode iterator and any_extend code iterator.
+ (vec_widen_<s>mult_hi_v8si, vec_widen_<s>mult_lo_v8si): New expanders.
+ (vec_widen_smult_hi_v4si, vec_widen_smult_lo_v4si): Enable
+ also for TARGET_SSE4_1 using pmuldq insn.
+ (sdot_prodv8hi): Macroize using VI2_AVX2 iterator.
+ (sse2_sse4_1): New code attr.
+ (udot_prodv4si): Macroize using any_extend code iterator.
+ (<s>dot_prodv8si): New expander.
+
+2011-10-14 Yakovlev Vladimir <vladimir.b.yakovlev@intel.com>
+
+ * config/i386/i386.c (atom_cost): Changed cost for loading
+ QImode using movzbl.
+
+2011-10-14 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_init_builtins): Fix typo in my
+ change on October 11th, 2011.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_interleave_high<mode>,
+ vec_interleave_low<mode>): Add AVX2 expanders for VI_256 modes.
+ * config/i386/i386.c (expand_vec_perm_interleave3): New function.
+ (ix86_expand_vec_perm_builtin_1): Call it.
+
+2011-10-14 Georg-Johann Lay <avr@gjlay.de>
+
+ Fix thinko from r179765
+ * config/avr/avr.c (avr_option_override): Don't override
+ flag_omit_frame_pointer if not actually needed.
+
+2011-10-14 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/46278
+ * doc/invoke.texi (AVR Options): Document -mstrict-X.
+
+ * config/avr/avr.opt (-mstrict-X): New option.
+ (avr_strict_X): New variable reflecting -mstrict-X.
+ * config/avr/avr.c (avr_reg_ok_for_addr_p): Add parameter
+ outer_code and pass it down to avr_regno_mode_code_ok_for_base_p.
+ (avr_legitimate_address_p): Pass outer_code to
+ avr_reg_ok_for_addr_p and use that function in case PLUS.
+ (avr_mode_code_base_reg_class): Depend on avr_strict_X.
+ (avr_regno_mode_code_ok_for_base_p): Ditto, and depend on outer_code.
+ (avr_option_override): Disable -fcaller-saves if -mstrict-X is on.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (neg<mode>2): Use VI_AVX2 iterator instead
+ of VI_128.
+
+ * config/i386/sse.md (mulv2di3): Macroize using VI8_AVX2 iterator.
+ (ashl<mode>3): Use VI248_AVX2 iterator instead of VI248_128.
+ Use <sseinsnmode> instead of TI in mode attr.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * config/arm/linux-atomic-64bit.c: New (based on linux-atomic.c).
+ * config/arm/linux-atomic.c: Change comment to point to 64bit version.
+ (SYNC_LOCK_RELEASE): Instantiate 64bit version.
+ * config/arm/t-linux-eabi: Pull in linux-atomic-64bit.c.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * config/arm/arm.c (arm_output_ldrex): Support ldrexd.
+ (arm_output_strex): Support strexd.
+ (arm_output_it): New helper to output it in Thumb2 mode only.
+ (arm_output_sync_loop): Support DI mode. Change comment to
+ not support const_int.
+ (arm_expand_sync): Support DI mode.
+ * config/arm/arm.h (TARGET_HAVE_LDREXBHD): Split into LDREXBH
+ and LDREXD.
+ * config/arm/iterators.md (NARROW): move from sync.md.
+ (QHSD): New iterator for all current ARM integer modes.
+ (SIDI): New iterator for SI and DI modes only.
+ * config/arm/sync.md (sync_predtab): New mode_attr.
+ (sync_compare_and_swapsi): Fold into sync_compare_and_swap<mode>.
+ (sync_lock_test_and_setsi): Fold into sync_lock_test_and_setsi<mode>.
+ (sync_<sync_optab>si): Fold into sync_<sync_optab><mode>.
+ (sync_nandsi): Fold into sync_nand<mode>.
+ (sync_new_<sync_optab>si): Fold into sync_new_<sync_optab><mode>.
+ (sync_new_nandsi): Fold into sync_new_nand<mode>.
+ (sync_old_<sync_optab>si): Fold into sync_old_<sync_optab><mode>.
+ (sync_old_nandsi): Fold into sync_old_nand<mode>.
+ (sync_compare_and_swap<mode>): Support SI & DI.
+ (sync_lock_test_and_set<mode>): Likewise.
+ (sync_<sync_optab><mode>): Likewise.
+ (sync_nand<mode>): Likewise.
+ (sync_new_<sync_optab><mode>): Likewise.
+ (sync_new_nand<mode>): Likewise.
+ (sync_old_<sync_optab><mode>): Likewise.
+ (sync_old_nand<mode>): Likewise.
+ (arm_sync_compare_and_swapsi): Turn into iterator on SI & DI.
+ (arm_sync_lock_test_and_setsi): Likewise.
+ (arm_sync_new_<sync_optab>si): Likewise.
+ (arm_sync_new_nandsi): Likewise.
+ (arm_sync_old_<sync_optab>si): Likewise.
+ (arm_sync_old_nandsi): Likewise.
+ (arm_sync_compare_and_swap<mode> NARROW): use sync_predtab, fix indent.
+ (arm_sync_lock_test_and_setsi<mode> NARROW): Likewise.
+ (arm_sync_new_<sync_optab><mode> NARROW): Likewise.
+ (arm_sync_new_nand<mode> NARROW): Likewise.
+ (arm_sync_old_<sync_optab><mode> NARROW): Likewise.
+ (arm_sync_old_nand<mode> NARROW): Likewise.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ PR target/48126
+ * config/arm/arm.c (arm_output_sync_loop): Move label before barrier.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * config/arm/arm.h (TARGET_HAVE_DMB_MCR): MCR Not available in Thumb1.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * doc/invoke.texi ([Wformat-zero-length]): Tidy.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * gimple.c (walk_stmt_load_store_addr_ops): Call visit_addr also
+ on COND_EXPR/VEC_COND_EXPR comparison operands if they are ADDR_EXPRs.
+
+2011-10-14 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50723
+ * ipa-split.c (split_function): Use GSI_CONTINUE_LINKING.
+
+2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * gengtype.c (files_rules): Added rules for objc/objc-map.h and
+ objc/objc-map.c.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/17212
+ * doc/invoke.texi ([Wformat-zero-length]): Update.
+
+2011-10-14 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR bootstrap/50699
+ * config/darwin.c (darwin_patch_builtin): Adjust argument type. Only
+ build for powerpc targets. (darwin_patch_builtins): Only build for
+ powerpc targets.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (*avx_cvtdq2pd256_2): Rename to...
+ (avx_cvtdq2pd256_2): ... this.
+ (sseunpackfltmode): New mode attr.
+ (vec_unpacks_float_hi_v8hi, vec_unpacks_float_lo_v8hi,
+ vec_unpacku_float_hi_v8hi, vec_unpacku_float_lo_v8hi): Macroize
+ using VI2_AVX2 iterator.
+ (vec_unpacku_float_hi_v8si, vec_unpacku_float_lo_v8si): New expanders.
+
+2011-10-13 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (plusminus): New code iterator.
+ (plusminus_insn): New code attr.
+ (addv2si3, subv2si3, addv4hi3, subv4hi3, addv2hi3, subv2hi3): Merge
+ using plusminus and plusminus_insn.
+ (fpadd64_vis, fpsub64_vis): Likewise.
+
+2011-10-13 Richard Henderson <rth@redhat.com>
+
+ * doc/md.texi (vec_perm): Document fallback to byte permutation.
+ * genopinit.c (optabs): Add vec_perm_const.
+ * optabs.c (can_vec_perm_expr_p): Rename from expand_vec_perm_expr_p.
+ Reject non-vector modes. Allow fallback to byte permutation.
+ (expand_vec_perm_expr_1): Split out from ...
+ (expand_vec_perm_expr): ... here. Allow fallback to byte permutation.
+ * optabs.h (DOI_vec_perm_const, vec_perm_const_optab): New.
+ * tree-vect-generic.c (lower_vec_perm): Update for name change.
+
+2011-10-13 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/altivec.md (vec_permv16qi): New pattern.
+
+ * config/rs6000/spu.md (vec_permv16qi): New pattern.
+
+ * config/i386/i386.c (ix86_expand_vec_perm_const): New.
+ * config/i386/i386-protos.h: Update.
+ * config/i386/sse.md (VEC_PERM_CONST): New mode iterator.
+ (vec_perm_const<VEC_PERM_CONST>): New expander.
+
+ * optabs.c (expand_vector_broadcast): New.
+ (expand_binop): Expand scalar shifts of vectors to vector shifts
+ of vectors, if the former isn't supported.
+ * tree-vect-generic.c (expand_vector_operations_1): Don't do that
+ here; always simplify to scalar shift of vector if possible.
+
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init): Fix mode
+ test for vector splat.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_set<mode>): Change V_128 iterator mode to V.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+ Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa.c (maybe_optimize_var): Drop TREE_ADDRESSABLE from vector
+ or complex vars even if their DECL_UID is in not_reg_needs bitmap.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (reduc_umin_v8hi): New pattern.
+ * config/i386/i386.c (ix86_build_const_vector): Handle
+ also V32QI, V16QI, V16HI and V8HI modes.
+ (emit_reduc_half): New function.
+ (ix86_expand_reduc): Use phminposuw insn for V8HImode UMIN.
+ Use emit_reduc_half helper function.
+
+2011-10-13 Lawrence Crowl <crowl@google.com>
+ Diego Novillo <dnovillo@google.com>
+
+ * lto-streamer-in.c (input_struct_function_base): Factor out of ...
+ (input_function): ... here.
+ * lto-streamer-out.c (output_struct_function_base): Factor out of ...
+ (output_function): ... here.
+
+2011-10-13 Gabriel Charette <gchare@google.com>
+ Diego Novillo <dnovillo@google.com>
+
+ * streamer-hooks.h (struct streamer_hooks): Add hooks
+ input_location and output_location.
+ * lto-streamer-in.c (lto_input_location): Use
+ streamer_hooks.input_location, if set.
+ * lto-streamer-out.c (lto_output_location): Use
+ streamer_hooks.output_location, if set.
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/invoke.texi (SPARC options): Document -mfix-at697f.
+ * config/sparc/sparc.opt (mfix-at697f): New option.
+ * config/sparc/sparc.c (TARGET_MACHINE_DEPENDENT_REORG): Define.
+ (sparc_reorg): New function.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50712
+ * ipa-split.c (split_function): Always re-gimplify parameters
+ when they are not gimple vals before passing them. Properly
+ check for type compatibility.
+
+2011-10-13 Tom de Vries <tom@codesourcery.com>
+
+ * function.c (gimplify_parameters): Set number of arguments of call to
+ BUILT_IN_ALLOCA_WITH_ALIGN to 2.
+
+2011-10-13 Tom de Vries <tom@codesourcery.com>
+
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Set MEM_READONLY_P
+ for static const strings.
+ * varasm.c (build_constant_desc): Generate the memory location of the
+ constant using gen_const_mem.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50698
+ * tree-data-ref.c (split_constant_offset_1): Also process
+ offsets of &MEM.
+
+2011-10-12 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (UNSPEC_FPMERGE): Delete.
+ (UNSPEC_MUL16AU, UNSPEC_MUL8, UNSPEC_MUL8SU, UNSPEC_MULDSU): New
+ unspecs.
+ (fpmerge_vis): Remove inaccurate comment, represent using vec_select
+ of a vec_concat.
+ (vec_interleave_lowv8qi, vec_interleave_highv8qi): New insns.
+ (fmul8x16_vis, fmul8x16au_vis, fmul8sux16_vis, fmuld8sux16_vis):
+ Reimplement as unspecs and remove inaccurate comments.
+ (vis3_shift_patname): New code attr.
+ (<vis3_shift_insn><vbits>_vis): Rename to
+ "v<vis3_shift_patname><mode>3".
+ (vis3_addsub_ss_patname): New code attr.
+ (<vis3_addsub_ss_insn><vbits>_vis): Rename to
+ "<vis3_addsub_ss_patname><mode>3".
+ * config/sparc/sparc.c (sparc_vis_init_builtins): Update to
+ accommodate pattern name changes.
+
+ * config/sparc/sparc.h: Do not force TARGET_VIS3 and TARGET_FMAF
+ to zero when assembler lacks support for such instructions.
+ * config/sparc/sparc.c (sparc_option_override): Clear MASK_VIS3
+ and MASK_FMAF in defaults when assembler lacks necessary support.
+
+2011-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_unpacks_lo_<mode>,
+ vec_unpacks_hi_<mode>, vec_unpacku_lo_<mode>,
+ vec_unpacku_hi_<mode>): Change VI124_128 mode to VI124_AVX2.
+ * config/i386/i386.c (ix86_expand_sse_unpack): Handle
+ V32QImode, V16HImode and V8SImode for TARGET_AVX2.
+
+ * config/i386/sse.md (vec_avx2): New mode_attr.
+ (mulv16qi3): Macroize to cover also mulv32qi3 for TARGET_AVX2 into ...
+ (mul<mode>3): ... this.
+
+ * config/i386/i386.md (UNSPEC_VPERMDI): Remove.
+ * config/i386/i386.c (ix86_expand_vec_perm): Handle
+ V16QImode and V32QImode for TARGET_AVX2.
+ (MAX_VECT_LEN): Increase to 32.
+ (expand_vec_perm_blend): Add support for 32-byte integer
+ vectors with TARGET_AVX2.
+ (valid_perm_using_mode_p): New function.
+ (expand_vec_perm_pshufb): Add support for 32-byte integer
+ vectors with TARGET_AVX2.
+ (expand_vec_perm_vpshufb2_vpermq): New function.
+ (expand_vec_perm_vpshufb2_vpermq_even_odd): New function.
+ (expand_vec_perm_even_odd_1): Handle 32-byte integer vectors
+ with TARGET_AVX2.
+ (ix86_expand_vec_perm_builtin_1): Try expand_vec_perm_vpshufb2_vpermq
+ and expand_vec_perm_vpshufb2_vpermq_even_odd.
+ * config/i386/sse.md (VEC_EXTRACT_EVENODD_MODE): Add for TARGET_AVX2
+ 32-byte integer vector modes.
+ (vec_pack_trunc_<mode>): Use VI248_AVX2 instead of VI248_128.
+ (avx2_interleave_highv32qi, avx2_interleave_lowv32qi): Remove pasto.
+ (avx2_pshufdv3, avx2_pshuflwv3, avx2_pshufhwv3): Generate
+ 4 new operands.
+ (avx2_pshufd_1, avx2_pshuflw_1, avx2_pshufhw_1): Don't use
+ match_dup, instead add 4 new operands and require they have
+ right cross-lane values.
+ (avx2_permv4di): Change into define_expand.
+ (avx2_permv4di_1): New instruction.
+ (avx2_permv2ti): Use nonimmediate_operand instead of register_operand
+ for "xm" constrained operand.
+ (VEC_PERM_AVX2): Add V32QI and V16QI for TARGET_AVX2.
+
+ * config/i386/sse.md (avx2_gathersi<mode>,
+ avx2_gatherdi<mode>, avx2_gatherdi<mode>256): Add clobber of
+ match_scratch, change memory_operand to register_operand,
+ add (mem:BLK (scratch)) use.
+ (*avx2_gathersi<mode>, *avx2_gatherdi<mode>,
+ *avx2_gatherdi<mode>256): Add clobber of match_scratch,
+ add earlyclobber to the output operand and match_scratch,
+ add (mem:BLK (scratch)) use, change the other mem to match_operand.
+ Use %p6 instead of %c6 in the pattern.
+ * config/i386/i386.c (ix86_expand_builtin): Adjust for
+ operand 2 being a Pmode register_operand instead of memory_operand.
+
+2011-10-12 Kai Tietz <ktietz@redhat.com>
+
+ * config/i386/i386.md (simple_return): Disable if TARGET_SEH is active.
+
+2011-10-12 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64.c (ia64_init_builtins): Fix unbalanced parentheses.
+
+2011-10-12 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-alias.c (maybe_skip_until): Cache also at the point
+ of the first store we visit in a basic-block.
+ (get_continuation_for_phi): Search for a candidate VUSE that
+ might dominates all others. Do pairwise disambiguation against
+ that candidate.
+
+2011-10-12 Paul Koning <pkoning@gcc.gnu.org>
+
+ PR tree-optimization/50189
+ * tree-vrp.c (extract_range_from_assert): Use the type of
+ the variable, not the limit.
+
+2011-10-12 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50700
+ * tree-object-size.c (addr_object_size): Simplify and treat
+ MEM_REF bases consistently.
+
+2011-10-12 Bernd Schmidt <bernds@codesourcery.com>
+
+ * function.c (prepare_shrink_wrap, bb_active_p): New function.
+ (thread_prologue_and_epilogue_insns): Use bb_active_p.
+ Call prepare_shrink_wrap, then recompute bb_active_p for the
+ last block.
+
+2011-10-12 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/50565
+ * convert.c (convert_to_integer): Do not narrow operands of
+ pointer subtraction.
+
+2011-10-12 Nick Clifton <nickc@redhat.com>
+
+ * config/arm/arm.h (EMIT_EABI_ATTRIBUTE): New macro. Used to
+ emit a .eabi_attribute assembler directive, possibly with a
+ comment attached.
+ * config/arm/arm.c (arm_file_start): Use the new macro.
+ * config/arm/arm-c.c (arm_output_c_attributes): Likewise.
+
+2011-10-12 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49939
+ * config/avr/avr.md (*movqi): Rename to movqi_insn.
+ (*call_insn): Rename to call_insn.
+ (*call_value_insn): Rename to call_value_insn.
+ * config/avr/avr.c (avr_2word_insn_p): New static function.
+ (jump_over_one_insn_p): Use it.
+
+2011-10-12 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * expr.h (copy_blkmode_to_reg): Declare.
+ * expr.c (copy_blkmode_to_reg): New function.
+ (expand_assignment): Don't expand register RESULT_DECLs before
+ the lhs. Use copy_blkmode_to_reg to copy BLKmode values into a
+ RESULT_DECL register.
+ (expand_expr_real_1): Handle BLKmode decls when looking for promotion.
+ * stmt.c (expand_return): Move BLKmode-to-register code into
+ copy_blkmode_to_reg.
+
+2011-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/49965
+ * config/sparc/sparc.md (mov<I:mode>cc): Do not save comparison code.
+ (mov<F:mode>cc): Likewise.
+
+2011-10-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * tree-ssa-address.c (copy_ref_info): Remove copy of TREE_THIS_NOTRAP.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * tree.h (built_in_decls): Delete old interface with two parallel
+ arrays to hold standard builtin declarations, and replace it with
+ a function based interface that can support creating builtins on
+ the fly in the future. Change all uses, and poison the old
+ names. Make sure 0 is not a legitimate builtin index.
+ (implicit_built_in_decls): Ditto.
+ (built_in_info): Ditto.
+ (BUILTIN_VALID_P): Ditto.
+ (builtin_decl_explicit): Ditto.
+ (builtin_decl_implicit): Ditto.
+ (set_builtin_decl): Ditto.
+ (set_builtin_decl_implicit_p): Ditto.
+ (builtin_decl_explicit_p): Ditto.
+ (builtin_decl_implicit_p): Ditto.
+ * tree-complex.c (expand_complex_libcall): Ditto.
+ * tree-loop-distribution.c (generate_memset_zero): Ditto.
+ * tree-ssa-strlen.c (get_string_length): Ditto.
+ (handle_builtin_strcpy): Ditto.
+ (handle_builtin_strcat): Ditto.
+ * tree.c (iterative_hash_expr): Ditto.
+ (local_define_builtin): Ditto.
+ (build_common_builtin_nodes): Ditto.
+ * builtins.c (built_in_decls): Ditto.
+ (implicit_built_in_decls): Ditto.
+ (built_in_info): Ditto
+ (expand_builtin_classify_type): Ditto.
+ (mathfn_built_in_1): Ditto.
+ (expand_builtin_cexpi): Ditto.
+ (expand_builtin_mempcpy_args): Ditto.
+ (expand_builtin_stpcpy): Ditto.
+ (gimplify_va_arg_expr): Ditto.
+ (expand_builtin_sync_operation): Ditto.
+ (build_builtin_expect_predicate): Ditto.
+ (fold_builtin_memory_op): Ditto.
+ (fold_builtin_strcpy): Ditto.
+ (fold_builtin_stpcpy): Ditto.
+ (fold_builtin_strncpy): Ditto.
+ (fold_builtin_interclass_mathfn): Ditto.
+ (fold_builtin_classify): Ditto.
+ (fold_builtin_2): Ditto.
+ (fold_builtin_strstr): Ditto.
+ (fold_builtin_strrchr): Ditto.
+ (fold_builtin_strpbrk): Ditto.
+ (fold_builtin_strcat): Ditto.
+ (fold_builtin_strncat): Ditto.
+ (fold_builtin_strcspn): Ditto.
+ (fold_builtin_fputs): Ditto.
+ (fold_builtin_sprintf): Ditto.
+ (fold_builtin_snprintf): Ditto.
+ (expand_builtin_memory_chk): Ditto.
+ (fold_builtin_memory_chk): Ditto.
+ (fold_builtin_stxcpy_chk): Ditto.
+ (fold_builtin_strncpy_chk): Ditto.
+ (fold_builtin_strcat_chk): Ditto.
+ (fold_builtin_strncat_chk): Ditto.
+ (fold_builtin_sprintf_chk_1): Ditto.
+ (fold_builtin_snprintf_chk_1): Ditto.
+ (fold_builtin_printf): Ditto.
+ (fold_builtin_fprintf): Ditto.
+ (fold_call_stmt): Ditto.
+ (set_builtin_user_assembler_name): Ditto.
+ * tree-emutls.c (emutls_common_1): Ditto.
+ * omp-low.c (scan_omp): Ditto.
+ (lower_rec_input_clauses): Ditto.
+ (lower_reduction_clauses): Ditto.
+ (expand_parallel_call): Ditto.
+ (expand_task_call): Ditto.
+ (maybe_catch_exception): Ditto.
+ (optimize_omp_library_calls): Ditto.
+ (expand_omp_for_generic): Ditto.
+ (expand_omp_for_static_nochunk): Ditto.
+ (expand_omp_for_static_chunk): Ditto.
+ (expand_omp_sections): Ditto.
+ (expand_omp_atomic_fetch_op): Ditto.
+ (expand_omp_atomic_pipeline): Ditto.
+ (expand_omp_atomic_mutex): Ditto.
+ (lower_omp_single_simple): Ditto.
+ (lower_omp_single_copy): Ditto.
+ (lower_omp_master): Ditto.
+ (lower_omp_ordered): Ditto.
+ (lower_omp_critical): Ditto.
+ * tree-ssa-ccp.c (optimize_stdarg_builtin): Ditto.
+ * builtins.c (DEF_BUILTIN_STUB): Ditto.
+ (BUILT_IN_NONE): Ditto.
+ * tree-ssa-math-opts.c (execute_optimize_bswap): Ditto.
+ * gimple-low.c (lower_function_body): Ditto.
+ (lower_builtin_setjmp): Ditto.
+ * c-decl.c (merge_decls): Ditto.
+ * tree-eh.c (lower_resx): Ditto.
+ (lower_resx): Ditto.
+ (lower_eh_dispatch): Ditto.
+ * function (gimplify_parameters): Ditto.
+ * c-typeck.c (build_function_call_vec): Ditto.
+ * gimplify.c (build_stack_save_restore): Ditto.
+ (gimplify_vla_decl): Ditto.
+ (gimplify_modify_expr_to_memcpy): Ditto.
+ (gimplify_modify_expr_to_memset): Ditto.
+ (gimplify_variable_sized_compare): Ditto.
+ (gimplify_function_tree): Ditto.
+ * calls.c (emit_call_1): Ditto.
+ * tree-ssa-forprop.c (simplify_builtin_call): Ditto.
+ * tree-nested.c (convert_nl_goto_reference): Ditto.
+ (convert_tramp_reference_op): Ditto.
+ (finalize_nesting_tree_1): Ditto.
+ * tree-ssa-loop-prefetch.c (issue_prefetch_ref): Ditto.
+ (tree_ssa_prefetch_arrays): Ditto.
+ * tree-streamer-in.c (streamer_get_builtin_tree): Ditto.
+ * system.h (built_in_decls): Ditto.
+ (implicit_built_in_decls): Ditto.
+ * tree-vect-generic.c (expand_vector_operations_1): Ditto.
+ * config/sparc/sparc.c (sparc_gimplify_va_arg): Ditto.
+ * config/i386/i386.c (ix86_gimplify_va_arg): Ditto.
+ (ix86_veclibabi_svml): Ditto.
+ (ix86_veclibabi_acml): Ditto.
+ * config/vms/vms.c (vms_patch_builtins): Ditto.
+ * config/ia64/ia64.c (ia64_init_builtins): Ditto.
+ * config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Ditto.
+ (rs6000_builtin_vectorized_libmass): Ditto.
+ (rs6000_init_builtins): Ditto.
+ * config/darwin.c (darwin_override_options): Ditto.
+ (darwin_patch_builtin): Ditto.
+ (darwin_rename_builtins): Ditto.
+ * config/pa/pa.c (pa_init_builtins): Ditto.
+
+2011-10-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * tree.h (copy_ref_info): Expose existing function.
+ * tree-ssa-loop-ivopts.c (copy_ref_info): Move function to...
+ * tree-ssa-address.c (copy_ref_info): ...here, and remove static token.
+
+2011-10-11 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr-protos.h (avr_mode_code_base_reg_class): New
+ prototype.
+ (avr_regno_mode_code_ok_for_base_p): New prototype.
+ * config/avr/avr.h (BASE_REG_CLASS): Remove.
+ (REGNO_OK_FOR_BASE_P): Remove.
+ (REG_OK_FOR_BASE_NOSTRICT_P): Remove.
+ (REG_OK_FOR_BASE_STRICT_P): Remove.
+ (MODE_CODE_BASE_REG_CLASS): New define.
+ (REGNO_MODE_CODE_OK_FOR_BASE_P): New define.
+ * config/avr/avr.c (avr_mode_code_base_reg_class): New function.
+ (avr_regno_mode_code_ok_for_base_p): New function.
+ (avr_reg_ok_for_addr_p): New static function.
+ (avr_legitimate_address_p): Use it. Beautify.
+
+2011-10-11 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50447
+ * config/avr/avr.md (cc): Add out_plus attribute alternative.
+ (addsi3): Use it. Adapt avr_out_plus to new prototype. Use
+ avr_out_plus for all CONST_INT addends.
+ * config/avr/avr-protos.h (avr_out_plus): Change prototype.
+ * config/avr/avr.c (notice_update_cc): Call avr_out_plus on
+ CC_OUT_PLUS.
+ (avr_out_plus_1): Change prototype and report effect on cc0.
+ (avr_out_plus): Ditto.
+ (adjust_insn_length): Adapt call to avr_out_plus to new prototype.
+
+2011-10-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_expand_special_args_builtin): Remove
+ the extra break.
+
+2011-10-11 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
+
+ * doc/invoke.texi: Document new warning.
+ * common.opt (Wvector-operation-performance): Define new warning.
+ * tree-vect-generic.c (expand_vector_piecewise): Warn about expanded
+ vector operation.
+ (exapnd_vector_parallel): Warn about expanded vector operation.
+ (lower_vec_shuffle): Warn about expanded vector operation.
+ * c-typeck.c (c_build_vec_perm_expr): Store correct location
+ when creating VEC_PERM_EXPR.
+
+2011-10-11 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50204
+ * tree-ssa-alias.c (get_continuation_for_phi_1): Split out
+ two argument handling from ...
+ (get_continuation_for_phi): ... here. Handle arbitrary number
+ of PHI args.
+
+2011-10-11 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * modulo-sched.c: Fix comment typo. Mention the possibility
+ of using scheduling windows of II+1 cycles.
+
+2011-10-11 Tristan Gingold <gingold@adacore.com>
+
+ * doc/invoke.texi (C Dialect Options): Document
+ -fallow-parameterless-variadic-functions.
+ * c-parser.c (c_parser_parms_list_declarator): Handle it.
+
+2011-10-10 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.c (avr_option_override): Set
+ flag_omit_frame_pointer to 0 if frame pointer is needed for unwinding.
+
+2011-10-10 Uros Bizjak <ubizjak@gmail.com>
+
+ PR bootstrap/50665
+ * optabs.h (DOI_vec_perm): Rename from OTI_vec_perm. Move from enum
+ optab_index to enum direct_optab_index.
+ (vec_perm_optab): Update.
+
+2011-10-10 Anatoly Sokolov <aesok@post.ru>
+
+ * config/cris/cris.c (cris_preferred_reload_class): New function.
+ (TARGET_PREFERRED_RELOAD_CLASS): Define.
+ * config/cris/cris.h (PREFERRED_RELOAD_CLASS): Remove.
+
+2011-10-10 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.md (*tablejump_rjmp): Change insn condition to
+ !AVR_HAVE_JMP_CALL.
+ (*tablejump_lib): Change insn condition to AVR_HAVE_JMP_CALL.
+ (*tablejump_enh, *tablejump): Remove insns.
+ * config/avr/libgcc.S (__tablejump__): Use RET instead of EIND +
+ EIJMP for indirect jump. Use LPM Z+ where available.
+
+2011-10-10 Richard Henderson <rth@redhat.com>
+
+ * doc/md.texi (vec_perm_const): Fix typo in cindex.
+
+2011-10-10 Kirill Yukhin <kirill.yukhin@intel.com>
+ Yakovlev Vladimir <vladimir.b.yakovlev@intel.com>
+
+ * config/i386/sse.md (fma_fnmsub_<mode>): Fix a typo.
+
+2011-10-10 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50389
+ * gimple-fold.c (gimplify_and_update_call_from_tree): Do not
+ mark symbols for renaming. Append the VUSE to all statements
+ that possibly can have one.
+
+2011-10-10 Richard Guenther <rguenther@suse.de>
+
+ * ipa-split.c (pass_split_functions): Add verification TODOs.
+ (pass_feedback_split_functions): Likewise.
+
+2011-10-10 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50195
+ * fold-const.c (fold_binary_loc): Canonicalize x*x to pow (x, 2)
+ only when optimizing.
+
+2011-10-10 Nick Clifton <nickc@redhat.com>
+
+ PR middle-end/49801
+ * compare-elim.c (find_comparisons_in_bb): Use df_get_live_in and
+ df_get_live_out instead of accessing the bitmaps directly.
+ (execute_compare_elim_after_reload): Remove calls to df_set_flags,
+ df_live_add_problem and df_analyze.
+
+2011-10-10 Michael Matz <matz@suse.de>
+
+ PR middle-end/50638
+ * tree-emutls.c (gen_emutls_addr): Call add_referenced_var.
+
+2011-10-10 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * modulo-sched.c (ps_reg_move_info): Add num_consecutive_stages.
+ (SCHED_FIRST_REG_MOVE, SCHED_NREG_MOVES): Delete.
+ (node_sched_params): Remove first_reg_move and nreg_moves.
+ (ps_num_consecutive_stages, extend_node_sched_params): New functions.
+ (update_node_sched_params): Move up file.
+ (print_node_sched_params): Print the stage. Don't dump info related
+ to first_reg_move and nreg_moves.
+ (set_columns_for_row): New function.
+ (set_columns_for_ps): Move up file and use set_columns_for_row.
+ (schedule_reg_move): New function.
+ (schedule_reg_moves): Call extend_node_sched_params and
+ schedule_reg_move. Extend size of uses bitmap. Initialize
+ num_consecutive_stages. Return false if a move could not be
+ scheduled.
+ (apply_reg_moves): Don't emit moves here.
+ (permute_partial_schedule): Handle register moves.
+ (duplicate_insns_of_cycles): Remove for_prolog. Emit moves according
+ to the same stage-count test as ddg nodes.
+ (generate_prolog_epilog): Update calls accordingly.
+ (sms_schedule): Allow move-scheduling to add a new first stage.
+
+2011-10-10 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * modulo-sched.c (ps_insn): Adjust comment.
+ (ps_reg_move_info): New structure.
+ (partial_schedule): Add reg_moves field.
+ (SCHED_PARAMS): Use node_sched_param_vec instead of node_sched_params.
+ (node_sched_params): Turn first_reg_move into an identifier.
+ (ps_reg_move): New function.
+ (ps_rtl_insn): Cope with register moves.
+ (ps_first_note): Adjust comment and assert that the instruction
+ isn't a register move.
+ (node_sched_params): Replace with...
+ (node_sched_param_vec): ...this vector.
+ (set_node_sched_params): Adjust accordingly.
+ (print_node_sched_params): Take a partial schedule instead of a ddg.
+ Use ps_rtl_insn and ps_reg_move.
+ (generate_reg_moves): Rename to...
+ (schedule_reg_moves): ...this. Remove rescan parameter. Record each
+ move in the partial schedule, but don't emit it here. Don't perform
+ register substitutions here either.
+ (apply_reg_moves): New function.
+ (duplicate_insns_of_cycles): Use register indices directly,
+ rather than finding instructions using PREV_INSN. Use ps_reg_move.
+ (sms_schedule): Call schedule_reg_moves before committing to
+ a partial schedule. Try the next ii if the schedule fails.
+ Use apply_reg_moves instead of generate_reg_moves. Adjust
+ call to print_node_sched_params. Free node_sched_param_vec
+ instead of node_sched_params.
+ (create_partial_schedule): Initialize reg_moves.
+ (free_partial_schedule): Free reg_moves.
+
+2011-10-10 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * modulo-sched.c (ps_insn): Replace node field with an identifier.
+ (SCHED_ASAP): Replace with..
+ (NODE_ASAP): ...this macro.
+ (SCHED_PARAMS): New macro.
+ (SCHED_TIME, SCHED_FIRST_REG_MOVE, SCHED_NREG_MOVES, SCHED_ROW)
+ (SCHED_STAGE, SCHED_COLUMN): Redefine using SCHED_PARAMS.
+ (node_sched_params): Remove asap.
+ (ps_rtl_insn, ps_first_note): New functions.
+ (set_node_sched_params): Use XCNEWVEC. Don't copy across the
+ asap values.
+ (print_node_sched_params): Use SCHED_PARAMS and NODE_ASAP.
+ (generate_reg_moves): Pass ids to the SCHED_* macros.
+ (update_node_sched_params): Take a ps insn identifier rather than
+ a node as parameter. Use ps_rtl_insn.
+ (set_columns_for_ps): Update for above field and SCHED_* macro changes.
+ (permute_partial_schedule): Use ps_rtl_insn and ps_first_note.
+ (optimize_sc): Update for above field and SCHED_* macro changes.
+ Update calls to try_scheduling_node_in_cycle and
+ update_node_sched_params.
+ (duplicate_insns_of_cycles): Adjust for above field and SCHED_*
+ macro changes. Use ps_rtl_insn and ps_first_note.
+ (sms_schedule): Pass ids to the SCHED_* macros.
+ (get_sched_window): Adjust for above field and SCHED_* macro changes.
+ Use NODE_ASAP instead of SCHED_ASAP.
+ (try_scheduling_node_in_cycle): Remove node parameter. Update
+ call to ps_add_node_check_conflicts. Pass ids to the SCHED_* macros.
+ (sms_schedule_by_order): Update call to try_scheduling_node_in_cycle.
+ (ps_insert_empty_row): Adjust for above field changes.
+ (compute_split_row): Use ids rather than nodes.
+ (verify_partial_schedule): Adjust for above field changes.
+ (print_partial_schedule): Use ps_rtl_insn.
+ (create_ps_insn): Take an id rather than a node.
+ (ps_insn_find_column): Adjust for above field changes.
+ Use ps_rtl_insn.
+ (ps_insn_advance_column): Adjust for above field changes.
+ (add_node_to_ps): Remove node parameter. Update call to
+ create_ps_insn.
+ (ps_has_conflicts): Use ps_rtl_insn.
+ (ps_add_node_check_conflicts): Replace node parameter than an id.
+
+2011-10-10 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * modulo-sched.c (undo_replace_buff_elem): Delete.
+ (generate_reg_moves): Don't build and return an undo list.
+ (free_undo_replace_buff): Delete.
+ (sms_schedule): Adjust call to generate_reg_moves.
+ Don't call free_undo_replace_buff.
+
+2011-10-10 Matthias Klose <doko@ubuntu.com>
+
+ * common/config/m32c: Remove empty directory.
+
+2011-10-10 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.md (*mulhi3_enh): Treat squaring smarter.
+
+2011-10-10 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50652
+ * config/avr/avr-mcus.def (AVR_MCU): Set .data_section_start of
+ atmega164a to 0x100.
+
+2011-10-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-ssa-forwprop.c (forward_propagate_into_comparison): Do not make
+ the replacement if the conversion to the LHS type is not useless.
+
+2011-10-09 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50635
+ * tree-vect-patterns.c (vect_handle_widen_mult_by_const): Add
+ DEF_STMT to the list of statements to be replaced by the
+ pattern statements.
+ (vect_handle_widen_mult_by_const): Don't check TYPE_OUT.
+
+2011-10-09 Anatoly Sokolov <aesok@post.ru>
+
+ * system.h: Commit forgotten hunk in previous patch.
+ (OUTPUT_ADDR_CONST_EXTRA): Poison.
+
+2011-10-08 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ PR libobjc/50428
+ * doc/objc.texi (Garbage Collection): Updated example to protect
+ +initialize against execution in subclasses.
+
+2011-10-07 Richard Henderson <rth@redhat.com>
+
+ * doc/extend.texi (__builtin_shuffle): Improve the description to
+ include the modulus of the selector. Mention OpenCL.
+ * doc/md.texi (vec_perm, vec_perm_const): Document named patterns.
+
+ * tree.def (VEC_PERM_EXPR): Rename from VEC_SHUFFLE_EXPR.
+ * genopinit.c (optabs): Rename vshuffle to vec_perm.
+ * c-typeck.c (c_build_vec_perm_expr): Rename from
+ c_build_vec_shuffle_expr. Update for name changes.
+ * optabs.c (expand_vec_perm_expr_p): Rename from
+ expand_vec_shuffle_expr_p.
+ (expand_vec_perm_expr): Rename from expand_vec_shuffle_expr.
+ * optabs.h (OTI_vec_perm): Rename from DOI_vshuffle.
+ (vec_perm_optab): Rename from vshuffle_optab.
+ * expr.c, gimple-pretty-print.c, gimple.c, gimplify.c,
+ c-tree.h, c-parser.c, tree-cfg.c, tree-inline.c, tree-pretty-print.c,
+ tree-ssa-operands.c, tree-vect-generic.c: Update for name changes.
+
+ * config/i386/i386.c (ix86_expand_vec_perm): Rename from
+ ix86_expand_vshuffle.
+ * config/i386/i386-protos.h: Update.
+ * config/i386/sse.md (VEC_PERM_AVX2): Rename from VSHUFFLE_AVX2.
+ (vec_perm<VEC_PERM_AVX2>): Rename from vshuffle<VSHUFFLE_AVX2>.
+
+2011-10-07 Richard Henderson <rth@redhat.com>
+
+ * config/i386/predicates.md (avx2_pblendw_operand): New.
+ * config/i386/sse.md (sse4_1_pblendw): Un-macroize.
+ (avx2_pblendw, *avx2_pblendw): New expander and insn.
+
+2011-10-07 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (bdesc_args): Update code for
+ __builtin_ia32_palignr256. Change type of __builtin_ia32_pslldqi256,
+ and __builtin_ia32_psrldqi256 to V4DI_FTYPE_V4DI_INT_CONVERT.
+ (ix86_expand_args_builtin): Handle V4DI_FTYPE_V4DI_INT_CONVERT.
+ * config/i386/sse.md (mode iterator V16): Add V2TI.
+ (mode iterator SSESCALARMODE): Use V2TI not V4DI.
+ (mode attr ssse3_avx2): Add V2TI.
+ (avx2_lshrqv4di3, avx2_lshlqv4di3): Remove.
+
+2011-10-07 David S. Miller <davem@davemloft.net>
+
+ PR 50655
+ * configure.ac: Add .register directives to VIS3 test.
+ * configure: Regenerate.
+
+2011-10-07 Richard Henderson <rth@redhat.com>
+
+ * config.gcc (x86_64-*): Add core-avx-i, core-avx2 for with_cpu.
+
+2011-10-07 Richard Henderson <rth@redhat.com>
+
+ PR 49752
+ * fold-const.c (fold_checksum_tree): Remove out-of-date assert.
+
+2011-10-07 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/arm/predicates.md (shift_amount_operand): Remove constant
+ range check.
+ (shift_operator): Check range of constants for all shift operators.
+
+2011-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c (s390_emit_tls_call_insn): Remove assertion.
+ Load GOT pointer for non-pic builds.
+ (s390_load_got): Replace pic_offset_table_rtx with hardcoded r12.
+ (s390_emit_call): Likewise.
+
+2011-10-07 Tom de Vries <tom@codesourcery.com>
+
+ PR middle-end/50527
+ * tree.c (build_common_builtin_nodes): Add local_define_builtin for
+ BUILT_IN_ALLOCA_WITH_ALIGN. Mark that BUILT_IN_ALLOCA_WITH_ALIGN can
+ throw.
+ * builtins.c (expand_builtin_alloca): Handle BUILT_IN_ALLOCA_WITH_ALIGN
+ arglist. Set align for BUILT_IN_ALLOCA_WITH_ALIGN.
+ (expand_builtin): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
+ (is_inexpensive_builtin): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
+ * tree-ssa-ccp.c (evaluate_stmt): Set align for
+ BUILT_IN_ALLOCA_WITH_ALIGN.
+ (fold_builtin_alloca_for_var): Rename to ...
+ (fold_builtin_alloca_with_align): Set DECL_ALIGN from 2nd
+ BUILT_IN_ALLOCA_WITH_ALIGN argument.
+ (ccp_fold_stmt): Try folding BUILT_IN_ALLOCA_WITH_ALIGN using
+ fold_builtin_alloca_with_align.
+ (optimize_stack_restore): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
+ * builtins.def (BUILT_IN_ALLOCA_WITH_ALIGN): Declare using
+ DEF_BUILTIN_STUB.
+ * ipa-pure-const.c (special_builtin_state): Handle
+ BUILT_IN_ALLOCA_WITH_ALIGN.
+ * tree-ssa-alias.c (ref_maybe_used_by_call_p_1)
+ (call_may_clobber_ref_p_1): Same.
+ * function.c (gimplify_parameters): Lower vla to
+ BUILT_IN_ALLOCA_WITH_ALIGN.
+ * gimplify.c (gimplify_vla_decl): Same.
+ * cfgexpand.c (expand_call_stmt): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
+ * tree-mudflap.c (mf_xform_statements): Same.
+ * tree-ssa-dce.c (mark_stmt_if_obviously_necessary)
+ (mark_all_reaching_defs_necessary_1, propagate_necessity): Same.
+ * varasm.c (incorporeal_function_p): Same.
+ * tree-object-size.c (alloc_object_size): Same.
+ * gimple.c (gimple_build_call_from_tree): Same.
+
+2011-10-07 Bernd Schmidt <bernds@codesourcery.com>
+
+ * function.c (frame_required_for_rtx): Remove function.
+ (requires_stack_frame_p): New arg set_up_by_prologue. All callers
+ changed. Compute a set of mentioned registers and compare against
+ the new arg rather than calling frame_required_for_rtx.
+ (thread_prologue_and_epilogue_insns): Compute the set_up_by_prologue
+ reg set. Convert the unconverted_simple_returns mechanism to store
+ jump insns rather than their basic blocks. Also check the
+ orig_entry_edge destination for new blocks.
+
+2011-10-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50650
+ * tree-vect-patterns.c (vect_recog_mixed_size_cond_pattern): Don't
+ call vect_is_simple_cond here, instead fail if cond_expr isn't
+ COMPARISON_CLASS_P or if get_vectype_for_scalar_type returns NULL
+ for cond_expr's first operand.
+ * tree-vect-stmts.c (vect_is_simple_cond): Static again.
+ * tree-vectorizer.h (vect_is_simple_cond): Remove prototype.
+
+2011-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.md (DWH, dwh): New mode macros.
+ ("umulsidi3"): Extend to support "umulditi3" as well.
+
+2011-10-07 Uros Bizjak <ubizjak@gmail.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/50603
+ * config/i386/i386.c (ix86_fixup_binary_operands): Force src2 of
+ integer PLUS RTX to a register to improve address combine.
+
+2011-10-06 Richard Henderson <rth@redhat.com>
+
+ * combine-stack-adjust.c (maybe_move_args_size_note): Add after
+ parameter; use it to decide whether to merge two notes.
+ (combine_stack_adjustments_for_block): Use maybe_move_args_size_note
+ for the deallocation case as well.
+
+2011-10-06 Anatoly Sokolov <aesok@post.ru>
+
+ * system.h (OUTPUT_ADDR_CONST_EXTRA): Poison.
+ * doc/tm.texi.in (OUTPUT_ADDR_CONST_EXTRA): Remove documentation.
+ * doc/tm.texi: Regenerate.
+ * target.def (output_addr_const_extra): Use
+ hook_bool_FILEptr_rtx_false.
+ * targhooks.c (default_asm_output_addr_const_extra): Remove.
+ * targhooks.h (default_asm_output_addr_const_extra): Remove.
+ * hooks.c (hook_bool_FILEptr_rtx_false): New functions.
+ * hooks.h (hook_bool_FILEptr_rtx_false): Declare.
+
+2011-10-06 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (popcount<mode>2, clz<mode>2): Split up into...
+ (popcountdi2, popcountsi2, clzdi2, clzsi2): Explicit expanders, in the
+ SI mode 64-bit code gen case explicitly zero-extend and truncate.
+ (*popcount<mode>_sp64): Split up into...
+ (*popcountdi_sp64, *popcountsi_64): Explicit instantiations, and in the
+ SImode case use truncate.
+ (*clzsi_sp64): Rewrite to use truncate, and let the expander emit the
+ subtract so the compiler can optimize it.
+ (SIDI): Remove unused mode iterator.
+
+2011-10-06 Bernd Schmidt <bernds@codesourcery.com>
+
+ * function.c (thread_prologue_and_epilogue_insns): Emit split prologue
+ on the orig_entry_edge. Don't account for it in prologue_clobbered.
+
+2011-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * tree-vectorizer.h (vect_is_simple_cond): New prototype.
+ (NUM_PATTERNS): Change to 6.
+ * tree-vect-patterns.c (vect_recog_mixed_size_cond_pattern): New
+ function.
+ (vect_vect_recog_func_ptrs): Add vect_recog_mixed_size_cond_pattern.
+ (vect_mark_pattern_stmts): Don't create stmt_vinfo for def_stmt
+ if it already has one, and don't set STMT_VINFO_VECTYPE in it
+ if it is already set.
+ * tree-vect-stmts.c (vect_mark_stmts_to_be_vectorized): Handle
+ COND_EXPR in pattern stmts.
+ (vect_is_simple_cond): No longer static.
+
+2001-10-06 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_vshuffle): Add AVX2 support.
+ * config/i386/sse.md (sseshuffint): Remove.
+ (sseintvecmode): Support V16HI, V8HI, V32QI, V16QI.
+ (VSHUFFLE_AVX2): New mode iterator.
+ (vshuffle<mode>): Use it.
+ (avx_vec_concat<V_256>): Rename from *vec_concat<V_256>_avx.
+
+ * config/i386/i386.c (ix86_expand_sse_movcc): Use correct mode
+ for vector_all_ones_operand.
+ (ix86_expand_int_vcond): Distinguish between comparison mode
+ and data mode. Allow them to differ.
+ (ix86_expand_vshuffle): Don't force data mode to match maskmode.
+
+2001-10-06 Richard Henderson <rth@redhat.com>
+
+ * optabs.c (expand_vec_shuffle_expr): Use the proper mode for the
+ mask operand. Tidy the code.
+
+2011-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-patterns.c (vect_pattern_recog_1): Use
+ vect_recog_func_ptr typedef for the first argument.
+ (vect_pattern_recog): Rename vect_recog_func_ptr variable
+ to vect_recog_func, use vect_recog_func_ptr typedef for it.
+
+ PR tree-optimization/49279
+ * tree-ssa-structalias.c (find_func_aliases): Don't handle
+ CAST_RESTRICT.
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Allow
+ restrict propagation.
+ * tree-ssa.c (useless_type_conversion_p): Don't return false
+ if TYPE_RESTRICT differs.
+
+2011-10-06 Bernd Schmidt <bernds@codesourcery.com>
+
+ * function.c (thread_prologue_and_epilogue_insns): Build a vector
+ of unconverted simple return blocks rather than trying to
+ recompute them later based on bb_flags bitmap tests.
+
+2011-10-06 Michael Matz <matz@suse.de>
+
+ * tree-flow.h (get_var_ann): Don't declare.
+ * tree-flow-inline.h (get_var_ann): Remove.
+ (set_is_used): Use var_ann, not get_var_ann.
+ * tree-dfa.c (add_referenced_var): Inline body of get_var_ann.
+ * tree-profile.c (gimple_gen_edge_profiler): Call
+ find_referenced_var_in.
+ (gimple_gen_interval_profiler): Ditto.
+ (gimple_gen_pow2_profiler): Ditto.
+ (gimple_gen_one_value_profiler): Ditto.
+ (gimple_gen_average_profiler): Ditto.
+ (gimple_gen_ior_profiler): Ditto.
+ (gimple_gen_ic_profiler): Ditto plus call add_referenced_var.
+ (gimple_gen_ic_func_profiler): Call add_referenced_var.
+ * tree-mudflap.c (execute_mudflap_function_ops): Call
+ add_referenced_var.
+
+2011-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-patterns.c (vect_handle_widen_mult_by_const): For lhs
+ don't set SSA_NAME_DEF_STMT that has been already set by
+ gimple_build_assign_with_ops.
+ (vect_recog_pow_pattern, vect_recog_widen_sum_pattern,
+ vect_operation_fits_smaller_type, vect_recog_over_widening_pattern):
+ Likewise.
+
+ * tree.h (avoid_folding_inline_builtin): New prototype.
+ * builtins.c (avoid_folding_inline_builtin): No longer static.
+ * gimple-fold.c (gimple_fold_builtin): Give up if
+ avoid_folding_inline_builtin returns true.
+
+2011-10-06 Richard Guenther <rguenther@suse.de>
+
+ * tree-vect-generic.c (vector_element): Look at previous
+ generated results.
+
+2011-10-06 David Edelsohn <dje.gcc@gmail.com>
+
+ PR target/39950
+ * config/rs6000/aix.h (TARGET_OS_AIX_CPP_BUILTINS): Define
+ __powerpc__, __PPC__, __unix__.
+
+2011-10-06 Michael Matz <matz@suse.de>
+
+ * i386/i386.opt (recip_mask, recip_mask_explicit,
+ x_recip_mask_explicit): New variables and cl_target member.
+ (mrecip=): New option.
+ * i386/i386.h (RECIP_MASK_DIV, RECIP_MASK_SQRT, RECIP_MASK_VEC_DIV,
+ RECIP_MASK_VEC_SQRT, RECIP_MASK_ALL, RECIP_MASK_NONE): New bitmasks.
+ (TARGET_RECIP_DIV, TARGET_RECIP_SQRT, TARGET_RECIP_VEC_DIV,
+ TARGET_RECIP_VEC_SQRT): New tests.
+ * i386/i386.md (divsf3): Check TARGET_RECIP_DIV.
+ (sqrt<mode>2): Check TARGET_RECIP_SQRT.
+ * i386/sse.md (div<mode>3): Check TARGET_RECIP_VEC_DIV.
+ (sqrt<mode>2): Check TARGET_RECIP_VEC_SQRT.
+ * i386/i386.c (ix86_option_override_internal): Set recip_mask
+ for -mrecip and -mrecip=options.
+ (ix86_function_specific_save): Save recip_mask_explicit.
+ (ix86_function_specific_restore): Restore recip_mask_explicit.
+
+ * doc/invoke.texi (ix86 Options): Document the new option.
+
+2011-10-06 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR target/49049
+ * config/arm/arm.md (arm_subsi3_insn): Lose the last alternative.
+
+2011-10-06 Ulrich Weigand <ulrich.weigand@linaro.org>
+
+ PR target/50305
+ * config/arm/arm.c (arm_legitimize_reload_address): Recognize
+ output of a previous pass through legitimize_reload_address.
+ Do not attempt to optimize addresses if the base register is
+ equivalent to a constant.
+
+2011-10-06 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * function.c (thread_prologue_and_epilogue_insns): Mark
+ last_bb_active as possibly unused. It is unused for targets which
+ do neither have "return" nor "simple_return" expanders.
+
+2011-10-06 Richard Guenther <rguenther@suse.de>
+
+ * fold-const.c (fold_ternary_loc): Also fold non-constant
+ vector CONSTRUCTORs. Make more efficient.
+ * tree-ssa-dom.c (cprop_operand): Don't handle virtual operands.
+ (cprop_into_stmt): Don't propagate into virtual operands.
+ (optimize_stmt): Really dump original statement.
+
+2011-10-06 Nick Clifton <nickc@redhat.com>
+
+ * config/rx/rx.md (smin3): Revert previous delta.
+
+2011-10-06 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/38884
+ * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle partial
+ reads from aggregate SSA names.
+
+2011-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-patterns.c (vect_pattern_recog_1): Add stmts_to_replace
+ argument, truncate it at the beginning instead of allocating there
+ and freeing at the end.
+ (vect_pattern_recog): Allocate stmts_to_replace here and free at end,
+ pass its address to vect_pattern_recog_1.
+
+2011-10-05 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.opt (POPC): New option.
+ * doc/invoke.texi: Document it.
+ * config/sparc/sparc.c (sparc_option_override): Enable MASK_POPC by
+ default on Niagara-2 and later.
+ * config/sparc/sparc.h (CLZ_DEFINED_VALUE_AT_ZERO): Define.
+ * config/sparc/sparc.md (SIDI): New mode iterator.
+ (ffsdi2): Delete commented out pattern and comments.
+ (popcount<mode>2, clz<mode>2): New expanders.
+ (*popcount<mode>_sp64, popcountsi_v8plus, popcountdi_v8plus,
+ *clzdi_sp64, clzdi_v8plus, *clzsi_sp64, clzsi_v8plus): New insns.
+
+2011-10-06 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
+
+ PR middle-end/50607
+ * c-tree.h (c_expr_t): New typedef for struct c_expr.
+ (C_EXPR_APPEND): New macro.
+ * c-parser.c (c_parser_get_builtin_args): Preserve
+ original_tree_code of c_expr structure.
+ (c_parser_postfix_expression): Adjust to the new function.
+
+2011-10-05 Bernd Schmidt <bernds@codesourcery.com>
+
+ * function.c (thread_prologue_and_epilogue_insns): Don't shrink-wrap
+ if profiling after the prologue.
+
+2011-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50613
+ * tree-ssa-strlen.c (find_equal_ptrs): If CASE_CONVERT
+ operand is ADDR_EXPR, fallthru into ADDR_EXPR handling,
+ and if it is neither that not SSA_NAME, give up.
+
+2011-10-05 Richard Henderson <rth@redhat.com>
+
+ * tree-vect-generic.c (vector_element): Never fail. Use
+ build_zero_cst. Tidy up type references.
+ (lower_vec_shuffle): Never fail. Mask shuffle indicies. Reduce
+ code duplication. Do update_stmt here ...
+ (expand_vector_operations_1): ... not here.
+
+ * config/i386/i386.c (ix86_expand_vshuffle): Never fail. Handle
+ TARGET_XOP. Fix pshufb constant vector creation. Reduce code
+ duplication. Handle V2DI without SSE4.1.
+ * config/i386/i386-protos.h (ix86_expand_vshuffle): Update decl.
+ * config/i386/i386.md (vshuffle<V_128>): Remove assert for ok.
+
+2011-10-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (distance_non_agu_define): Simplify calculation
+ of "found". Simplify return value calculation.
+ (distance_agu_use): Ditto.
+
+2011-10-05 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR bootstrap/50621
+ * config/i386/i386.c (ix86_add_cfa_restore_note): Omit notes only
+ if the function was not shrink-wrapped.
+ (ix86_expand_epilogue): Ensure queued cfa_adjust notes are attached
+ to an insn.
+ * function.c (thread_prologue_and_epilogue_insns): Make sure the
+ shrink_wrapped flag is set even if there is no dump file.
+
+2011-10-05 DJ Delorie <dj@redhat.com>
+ Nick Clifton <nickc@redhat.com>
+
+ * config/rx/rx.opt (mpid): Define.
+ * config/rx/t-rx (MULTILIB_OPTIONS): Add -mpid
+ (MULTILIB_DIRNAMES): Add pid.
+ * config/rx/rx.c (rx_gp_base_regnum_val, rx_pid_base_regnum_val)
+ (rx_num_interrupt_regs): New variable.
+ (rx_gp_base_regnum): New function. Returns the number of the
+ small data area register.
+ (rx_pid_base_regnum): New function. Returns the number of the pid
+ base register.
+ (rx_decl_for_addr): New function. Returns the symbolic part of a MEM.
+ (rx_pid_data_operand): New function. Returns whether an object is
+ in the position independent data area.
+ (rx_legitimize_address): New function. Puts undecided PID
+ objects in the PID data area.
+ (rx_is_legitimate_address): Add support for PID operands.
+ (rx_print_operand_address): Likewise.
+ (rx_print_operand): Likewise.
+ (rx_maybe_pidify_operand): New function. Determine if an operand
+ is suitable for PID addressing.
+ (rx_gen_move_template): Add PID support.
+ (rx_conditional_register_usage): Likewise.
+ (rx_option_override): Initialise rx_num_interrupt_regs.
+ (rx_is_legitimate_constant): Add support for PID constants.
+ (TARGET_LEGITIMIZE_ADDRESS): Define.
+ * config/rx/constraints.md (Rpid): Define.
+ (Rpda): Define.
+ * config/rx/rx.md (UNSPEC_PID_ADDR): Define.
+ (tablejump): Add PID support.
+ (mov<>): Likewise.
+ (mov<>_internal): Likewise.
+ (addsi3): Convert to an expander. Add PID support.
+ (pid_addr): New pattern.
+ * config/rx/rx.h (CPP_SPEC): Define.
+ (ASM_SPEC): Pass -mpid and -mint-register on to assembler.
+ (CASE_VECTOR_PC_RELATIVE): Define.
+ (JUMP_TABLES_IN_TEXT_SECTION): Enable for PID mode.
+ * config/rx/rx-protos.h (rx_maybe_pidify_operand): Prototype.
+ * doc/invoke.texi (RX Options): Document -mpid command line option.
+
+2011-10-05 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/38885
+ * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle partial reads
+ from constants.
+
+2011-10-05 Bernd Schmidt <bernds@codesourcery.com>
+
+ * doc/invoke.texi (-fshrink-wrap): Document.
+ * opts.c (default_options_table): Add it.
+ * common.opt (fshrink-wrap): Add.
+ * function.c (emit_return_into_block): Remove useless declaration.
+ (record_hard_reg_uses_1, record_hard_reg_uses, frame_required_for_rtx,
+ requires_stack_frame_p, gen_return_pattern): New static functions.
+ (emit_return_into_block): New arg simple_p. All callers changed.
+ Use gen_return_pattern.
+ (thread_prologue_and_epilogue_insns): Implement shrink-wrapping.
+ * config/i386/i386.md (return): Expand into a simple_return.
+ (simple_return): New expander):
+ (simple_return_internal, simple_return_internal_long,
+ simple_return_pop_internal_long, simple_return_indirect_internal):
+ Renamed from return_internal, return_internal_long,
+ return_pop_internal_long and return_indirect_internal; changed to use
+ simple_return.
+ * config/i386/i386.c (ix86_expand_epilogue): Adjust to expand
+ simple returns.
+ (ix86_pad_returns): Likewise.
+ * function.h (struct rtl_data): Add member shrink_wrapped.
+ * cfgcleanup.c (outgoing_edges_match): If shrink-wrapped, edges that
+ are not jumps or sibcalls can't be compared.
+
+2011-10-05 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (vn_get_expr_for): Handle CONSTRUCTOR of
+ vector type.
+ (simplify_unary_expression): Handle BIT_FIELD_REFs.
+ (try_to_simplify): Handle BIT_FIELD_REFs.
+
+2011-10-05 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr-protos.h (avr_out_addto_sp): New prototype.
+ * config/avr/avr.c (avr_out_addto_sp): New function.
+ (adjust_insn_length): Handle ADJUST_LEN_ADDTO_SP.
+ * config/avr/avr.md (adjust_len): Add "addto_sp".
+ (*movhi_sp): Remove insn.
+ (*addhi3_sp_R_pc2, *addhi3_sp_R_pc3): Merge to *addhi3_sp_R.
+
+2011-10-05 Richard Guenther <rguenther@suse.de>
+
+ * gimple-fold.c (gimple_fold_stmt_to_constant_1): For ternary ops
+ with an embedded expression valueize and fold that as well.
+ * tree-ssa-sccvn.c (try_to_simplify): Also allow SSA name
+ results from gimple_fold_stmt_to_constant_1.
+
+2011-10-05 Nick Clifton <nickc@redhat.com>
+
+ * config/rx/rx.md (tablejump): Add missing label.
+ (adddi3_internal): Mark operand 0 as early-clobbered.
+ (smaxsi3): Revert previous delta.
+ (adc_internal): Fix whitespace in generated asm.
+ (adc_flags): Likewise.
+
+2011-10-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * expmed.c (expand_mult_highpart_optab): Replace optab_handler
+ with the new widening_optab_handler.
+
+2011-10-05 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50609
+ * gimple-fold.c (fold_array_ctor_reference): Also handle
+ vector typed constructors.
+ (fold_ctor_reference): Dispatch to fold_array_ctor_reference
+ for vector typed constructors.
+
+2011-10-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_emit_binop): New static function.
+ (ix86_split_lea_for_addr): Use ix86_emit_binop to emit add and shl
+ instructions.
+ (x86_output_mi_thunk): Use ix86_emit_binop to emit add instructions.
+
+2011-10-04 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (UNSPEC_FHADD, UNSPEC_FHSUB,
+ UNSPEC_XMUL): New unspecs.
+ (muldi3_v8plus): Use output_v8plus_mult.
+ (*naddsf3, *nadddf3, *nmulsf3, *nmuldf3, *nmuldf3_extend):
+ New VIS 3.0 combiner patterns.
+ (fhaddsf_vis, fhadddf_vis, fhsubsf_vis, fhsubdf_vis,
+ fnhaddsf_vis, fnhaddf_vis, umulxhi_vis, *umulxhi_sp64,
+ umulxhi_v8plus, xmulx_vis, *xmulx_sp64, xmulx_v8plus,
+ xmulxhi_vis, *xmulxhi_sp64, xmulxhi_v8plus): New VIS 3.0
+ builtins patterns.
+ * config/sparc/sparc.c (sparc_vis_init_builtins): Emit new builtins.
+ (output_v8plus_mult): New function.
+ * config/sparc/sparc-protos.h: Declare it.
+ * config/sparc/visintrin.h (__vis_fhadds, __vis_fhaddd,
+ __vis_fhsubs, __vis_fhsubd, __vis_fnhadds, __vis_fnhaddd,
+ __vis_umulxhi, __vis_xmulx, __vis_xmulxhi): New intrinsics.
+ * doc/extend.texi: Document new builtins.
+
+2011-10-04 Richard Henderson <rth@redhat.com>
+
+ * c-typeck.c (c_build_vec_shuffle_expr): Fix uninitialized variable.
+ Avoid save_expr unless two_arguments.
+
+2011-10-04 Ozkan Sezer <sezeroz@gmail.com>
+
+ * config/i386/mingw-w64.h (CPP_SPEC): Rename _REENTRANCE to _REENTRANT.
+ * config/i386/mingw32.h (CPP_SPEC): Likewise.
+
+2011-10-04 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/driver-sparc.c (cpu_names): Fix string for supersparc
+ under Linux.
+
+2011-10-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50604
+ * builtins.c (fold_builtin_strcpy, fold_builtin_stpcpy,
+ fold_builtin_strncpy, fold_builtin_stxcpy_chk): Ensure
+ last argument to memcpy has size_type_node type instead of ssizetype.
+ * tree-ssa-strlen.c (handle_builtin_memcpy): Use size_type_node
+ instead of TREE_TYPE (len) as type for newlen.
+
+ PR tree-optimization/50522
+ * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Don't test
+ TYPE_RESTRICT.
+ (ptr_derefs_may_alias_p): Call pt_solutions_same_restrict_base
+ unconditionally.
+
+ * fold-const.c (fold_unary_loc): Don't optimize
+ POINTER_PLUS_EXPR casted to TYPE_RESTRICT pointer by
+ casting the inner pointer if it isn't TYPE_RESTRICT.
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Don't through
+ casts from non-TYPE_RESTRICT pointer to TYPE_RESTRICT pointer.
+
+2011-10-04 Joseph Myers <joseph@codesourcery.com>
+
+ * config.gcc (i[34567]86-*-elf*, x86_64-*-elf*): Use i386/t-crtstuff.
+
+2011-10-04 Jan Hubicka <jh@suse.cz>
+
+ * lto-streamer.h (lto_input_toplevel_asms): Add order_base parameter.
+ * lto-streamer-in.c (lto_input_toplevel_asms): Stream in order.
+ * lto-streamer-out.c (lto_output_toplevel_asms): Stream out order.
+ * lto-cgraph.c (order_base): New static var.
+ (lto_output_node): Stream in order.
+ (lto_output_varpool_node): Stream out order.
+ (input_node): Stream in order.
+ (input_varpool_node): Stream out order.
+ (input_cgraph_1): Initialize order base; update call of
+ lto_input_toplevel_asms.
+
+2011-10-04 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50566
+ * config/avr/avr-protos.h (avr_legitimize_reload_address): New
+ prototype.
+ * config/avr/avr.h (LEGITIMIZE_RELOAD_ADDRESS): Copy worker code
+ from here...
+ * config/avr/avr.c (avr_legitimize_reload_address) ...to this new
+ function. Log if avr_log.legitimize_reload_address.
+
+2011-10-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc.c (sparc_fold_builtin): Use a sequence of tests.
+
+2011-10-04 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * longlong.h (smul_ppmm, sdiv_qrnnd): Add underscores to the local
+ variables. Fix second operand of DR. Swap inputs for sdiv_qrnnd.
+
+2011-10-03 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (fpack16_vis, fpackfix_vis, fpack32_vis): Make
+ GSR_REG an input operand to UNSPEC instead of a parallel USE.
+ (faligndata<V64I:mode>_vis): Likewise and use DI mode.
+ (alignaddrsi_vis, alignaddrdi_vis, alignaddrlsi_vis, alignaddrldi_vis):
+ Reference GSR_REG in DI mode, simplify convoluted expressions by using
+ zero_extract.
+ (bshuffle<V64I:mode>_vis): Reference GSR_REG in DI mode.
+
+2011-10-03 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * tree-eh.c (remove_unreachable_handlers): Obvious cleanup.
+
+2011-10-03 Jakub Jelinek <jakub@redhat.com>
+ Ian Lance Taylor <iant@google.com>
+
+ * godump.c (go_output_typedef): Support printing enum values that
+ don't fit in a signed HOST_WIDE_INT.
+
+2011-10-03 Anatoly Sokolov <aesok@post.ru>
+
+ * config/cris/cris.c (cris_output_addr_const_extra): Make static.
+ (TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Define.
+ * config/cris/cris.h (OUTPUT_ADDR_CONST_EXTRA): Remove.
+ * config/cris/cris-protos.h (cris_output_addr_const_extra): Remove.
+
+2011-10-03 Anatoly Sokolov <aesok@post.ru>
+
+ * config/m68k/m68k.c (m68k_output_addr_const_extra): Make static.
+ (TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Define.
+ * config/m68k/m68k.h (OUTPUT_ADDR_CONST_EXTRA): Remove.
+ * config/m68k/m68k-protos.h (m68k_output_addr_const_extra): Remove.
+
+2011-10-03 Steve Ellcey <sje@cup.hp.com>
+
+ PR target/49967
+ * configure.ac (gcc_cv_ld_static_dynamic): Define for *-*-hpux*.
+ (gcc_cv_ld_static_option): Ditto.
+ (gcc_cv_ld_dynamic_option): Ditto.
+ * configure: Regenerate.
+
+2011-10-03 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (bmask<P:mode>_vis): Split into explicit 'di'
+ and 'si' patterns which describe the GSR changes explicitly in the
+ RTL using zero_extract.
+ (bshuffle<V64I:mode>_vis): Put the GSR use inside of the unspec.
+
+ * config/sparc/sparc.md (bshuffle<V64I:mode>_vis): Don't wrap
+ GSR_REG in a USE, since it's now a true arg to the UNSPEC.
+
+2011-10-03 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
+
+ * optabs.c (expand_vec_shuffle_expr_p): New function. Checks
+ if given expression can be expanded by the target.
+ (expand_vec_shuffle_expr): New function. Expand VEC_SHUFFLE_EXPR
+ using target vector instructions.
+ * optabs.h: New optab vshuffle.
+ (expand_vec_shuffle_expr_p): New prototype.
+ (expand_vec_shuffle_expr): New prototype.
+ (vshuffle_optab): New optab.
+ * genopinit.c: Adjust to support vecshuffle.
+ * c-tree.h (c_build_vec_shuffle_expr): New prototype.
+ * expr.c (expand_expr_real_2): Adjust.
+ * c-typeck.c: (c_build_vec_shuffle_expr): Build a VEC_SHUFFLE_EXPR
+ recognizing the cases of two and three arguments.
+ (convert_arguments) (build_binary_op)
+ (scalar_to_vector) (build_array_ref): Spurious whitespace.
+ * gimplify.c (gimplify_exp): Adjusted to support VEC_SHUFFLE_EXPR.
+ * tree.def: New tree code VEC_SHUFFLE_EXPR.
+ * tree-inline.c (estimate_operator_cost): Recognize VEC_SHUFFLE_EXPR.
+ * tree-vect-generic.c (vector_element): New function. Returns an
+ element of the vector at the given position.
+ (lower_vec_shuffle): Checks if VEC_SHUFLLE_EXPR is supported
+ by the backend or expand an expression piecewise.
+ (expand_vector_operations_1): Adjusted.
+ (gate_expand_vector_operations_noop): New gate function.
+ * Makefile.in (tree-vect-generic.o): New include.
+ * gimple.c (get_gimple_rhs_num_ops): Adjust.
+ * tree-cfg.c (verify_gimple_assign_trenary): Verify VEC_SHUFFLE_EXPR.
+ * passes.c: Move veclower down.
+ * tree-pretty-print.c (dump_generic_node): Recognize
+ VEC_SHUFFLE_EXPR as valid expression.
+ * c-parser.c (c_parser_get_builtin_args): Helper function for the
+ builtins with variable number of arguments.
+ (c_parser_postfix_expression): Use a new helper function for
+ RID_CHOOSE_EXPR, RID_BUILTIN_COMPLEX and RID_BUILTIN_SHUFFLE.
+ * tree-ssa-operands: Adjust.
+ * c-family/c-common.c: New __builtin_shuffle keyword.
+ * c-family/c-common.h: New __builtin_shuffle keyword.
+ * gcc/doc/extend.texi: Adjust.
+
+ * gcc/config/i386/sse.md: (sseshuffint) New mode_attr. Correspondence
+ between the vector and the type of the mask when shuffling.
+ (vecshuffle<mode>): New expansion.
+ * gcc/config/i386/i386-protos.h (ix86_expand_vshuffle): New prototype.
+ * gcc/config/i386/i386.c (ix86_expand_vshuffle): New function.
+ (ix86_vectorize_builtin_vec_perm_ok): Adjust.
+
+2011-10-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50587
+ * tree-ssa-reassoc.c (init_range_entry): Stop iterating when
+ arg0 is not a SSA_NAME.
+
+2011-10-03 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * ipa-inline-analysis.c (MAX_TIME): Update comment.
+
+2011-10-02 Richard Henderson <rth@redhat.com>
+ David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (ashlsi3, *ashldi3_sp64): Remove
+ conditional insn type setting, we always emit a shift.
+ (*ashlsi3_extend, *lshrsi3_extend0): New patterns.
+ (*lshrsi3_extend): Rename to *lshrsi3_extend1.
+ * config/sparc/predicates.md (const_one_operand): Delete.
+
+2011-10-02 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * invoke.texi (SPARC Options): Refer to GNU/Linux.
+
+2011-10-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips.c (mips_frame_barrier): New function.
+ (mips_expand_prologue): Call it after allocating stack space.
+ (mips_deallocate_stack): New function.
+ (mips_expand_epilogue): Call mips_frame_barrier and
+ mips_deallocate_stack.
+
+2011-10-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR target/49696
+ * config/mips/sync.md (sync_<optab>_12): Allow zero operands.
+ (sync_old_<optab>_12, sync_new_<optab>_12, sync_nand_12): Likewise.
+ (sync_old_nand_12, sync_new_nand_12, test_and_set_12): Likewise.
+
2011-10-02 Jan Hubicka <jh@suse.cz>
* cgraphunit.c (verify_edge_count_and_frequency): Bounds check.
@@ -31,7 +2479,8 @@
* lto-symtab.c (lto_symtab_resolve_symbols): Do not resolve
when resolution is already availbale from plugin.
(lto_symtab_merge_decls_1): Handle LDPR_PREVAILING_DEF_IRONLY_EXP.
- * cgraph.c (ld_plugin_symbol_resolution): Add prevailing_def_ironly_exp.
+ * cgraph.c (ld_plugin_symbol_resolution): Add
+ prevailing_def_ironly_exp.
* lto-cgraph.c (LDPR_NUM_KNOWN): Update.
* ipa.c (varpool_externally_visible_p): IRONLY variables are never
externally visible.
@@ -56,12 +2505,12 @@
(vis3_shift_insn, vis3_addsub_ss_insn): New code attributes.
(cmask8<P:mode>_vis, cmask16<P:mode>_vis, cmask32<P:mode>_vis,
fchksm16_vis, <vis3_shift_insn><vbits>_vis, pdistn<mode>_vis,
- fmean16_vis, fpadd64_vis, fpsub64_vis, <vis3_addsub_ss_insn><vbits>_vis,
- fucmp<code>8<P:mode>_vis): New VIS 3.0 instruction patterns.
+ fmean16_vis, fpadd64_vis, fpsub64_vis,
+ <vis3_addsub_ss_insn><vbits>_vis, fucmp<code>8<P:mode>_vis): New
+ VIS 3.0 instruction patterns.
* config/sparc/sparc.c (sparc_option_override): Set MASK_VIS3 by
default when targetting capable cpus. TARGET_VIS3 implies
- TARGET_VIS2 and TARGET_VIS, and clear them when TARGET_FPU is
- disabled.
+ TARGET_VIS2 and TARGET_VIS, and clear them when TARGET_FPU is disabled.
(sparc_vis_init_builtins): Emit new VIS 3.0 builtins.
(sparc_fold_builtin): Do not eliminate cmask{8,16,32} when result
is ignored.
@@ -229,7 +2678,7 @@
2011-09-30 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
- PR target/50099
+ PR target/50099
* config/arm/iterators.md (qhs_zextenddi_cstr): New.
(qhs_zextenddi_op): New.
* config/arm/arm.md ("zero_extend<mode>di2"): Use them.
@@ -270,8 +2719,7 @@
2011-09-29 Nick Clifton <nickc@redhat.com>
Bernd Schmidt <bernds@codesourcery.com>
- * config/frv/frvbegin.c: Fix location of unwind-dw2-fde.h header
- file.
+ * config/frv/frvbegin.c: Fix location of unwind-dw2-fde.h header file.
* config/frv/frvend.c: Likewise.
* config/frv/frv.c (frv_function_prologue): Move misplaced
CALL_ARG_LOCATION notes back to their proper locations.
@@ -305,27 +2753,29 @@
2011-09-27 Andi Kleen <ak@linux.intel.com>
- * gcc.c (get_local_tick). Rename to get_random_number.
- Read from /dev/urandom.
- Add getpid call.
+ * gcc.c (get_local_tick). Rename to get_random_number. Read from
+ /dev/urandom. Add getpid call.
(compare_debug_dump_opt_spec_function): Drop getpid call.
2011-09-26 Andi Kleen <ak@linux.intel.com>
- * toplev.c (init_local_tick): Try reading random seed from /dev/urandom
+ * toplev.c (init_local_tick): Try reading random seed
+ from /dev/urandom.
2011-09-26 Andi Kleen <ak@linux.intel.com>
* hwint.h (HOST_WIDE_INT_PRINT_HEX_PURE): Add.
* lto-streamer.c (lto_get_section_name): Remove crc32_string.
Handle numerical random seed.
- * lto-streamer.h (lto_file_decl_data): Change id to unsigned HOST_WIDE_INT.
+ * lto-streamer.h (lto_file_decl_data): Change id to
+ unsigned HOST_WIDE_INT.
* toplev.c (random_seed): Add.
(init_random_seed): Change for numerical random seed.
(get_random_seed): Return as HOST_WIDE_INT.
(set_random_seed): Crc32 existing string.
* toplev.h (get_random_seed): Change to numercal return.
- * tree.c (get_file_function_name): Remove CRC. Handle numerical random seed.
+ * tree.c (get_file_function_name): Remove CRC. Handle
+ numerical random seed.
2011-09-29 Georg-Johann Lay <avr@gjlay.de>
@@ -350,8 +2800,7 @@
(c_objc_common_truthvalue_conversion): Adjust.
* tree-vect-generic.c (do_compare): Helper function.
(expand_vector_comparison): Check if hardware supports
- vector comparison of the given type or expand vector
- piecewise.
+ vector comparison of the given type or expand vector piecewise.
(expand_vector_operation): Treat comparison as binary
operation of vector type.
(expand_vector_operations_1): Adjust.
@@ -17512,8 +19961,6 @@
2011-04-29 Jan Hubicka <jh@suse.cz>
- * gcc.dg/tree-ssa/inline-10.c: New testcase.
- * gcc.dg/tree-ssa/inline-9.c: Disable partial inlining.
* ipa-inline.h (clause_t): Turn into unsigned int.
* ipa-inline-analysis.c (add_clause): Do more simplification.
(and_predicates): Shortcut more cases.
@@ -23338,7 +25785,6 @@
* dwarf2asm.c (dw2_asm_output_encoded_addr_rtx): Add missing
va_end.
* c-family/c-common.c (def_fn_type): Likewise.
- * ada/gcc-interface/utils.c (def_fn_type): Likewise.
* emit-rtl.c (gen_rtvec): Likewise.
* lto/lto-lang.c (def_fn_type): Likewise.
diff --git a/gcc/ChangeLog.google-integration b/gcc/ChangeLog.google-integration
index 0407ab6f575..2ea4cf8fd74 100644
--- a/gcc/ChangeLog.google-integration
+++ b/gcc/ChangeLog.google-integration
@@ -1,3 +1,7 @@
+2011-10-25 Diego Novillo <dnovillo@google.com>
+
+ Mainline merge rev 180234.
+
2011-10-03 Diego Novillo <dnovillo@google.com>
Mainline merge rev 179430.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index f17a6f27735..2f6b55c3ea3 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20111002
+20111020
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ab657262a91..103b15bbc7f 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2754,7 +2754,7 @@ tree-vect-slp.o: tree-vect-slp.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
$(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) tree-pretty-print.h \
- gimple-pretty-print.h $(TREE_DATA_REF_H)
+ gimple-pretty-print.h $(TREE_DATA_REF_H) langhooks.h
tree-vect-stmts.o: tree-vect-stmts.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
@@ -2806,7 +2806,8 @@ tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
$(TM_H) coretypes.h tree-iterator.h $(SCEV_H) langhooks.h \
$(TREE_PASS_H) value-prof.h output.h tree-pretty-print.h
tree-diagnostic.o : tree-diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS_DEF_H)
+ $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS_DEF_H) \
+ $(VEC_H)
fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
$(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \
@@ -3194,7 +3195,7 @@ tree-vect-generic.o : tree-vect-generic.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
$(TM_H) $(TREE_FLOW_H) $(GIMPLE_H) tree-iterator.h $(TREE_PASS_H) \
$(FLAGS_H) $(OPTABS_H) $(MACHMODE_H) $(EXPR_H) \
langhooks.h $(FLAGS_H) $(DIAGNOSTIC_H) gt-tree-vect-generic.h $(GGC_H) \
- coretypes.h insn-codes.h
+ coretypes.h insn-codes.h $(DIAGNOSTIC_H)
df-core.o : df-core.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \
@@ -3506,7 +3507,8 @@ regcprop.o : regcprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_ERROR_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
output.h $(RECOG_H) $(FUNCTION_H) $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \
- addresses.h reload.h $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(TARGET_H)
+ addresses.h reload.h $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(TARGET_H) \
+ regrename.h $(EMIT_RTL_H)
ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(REGS_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \
$(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h $(EXCEPT_H) $(TM_P_H) \
@@ -4075,6 +4077,7 @@ PREPROCESSOR_DEFINES = \
-DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
-DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
+ -DNATIVE_SYSTEM_HEADER_DIR=\"$(NATIVE_SYSTEM_HEADER_DIR)\" \
-DPREFIX=\"$(prefix)/\" \
-DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc/\" \
@TARGET_SYSTEM_ROOT_DEFINE@
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index a7be9a2af55..f839cfb222e 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,677 @@
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc-interface/trans.c (gigi, Sloc_to_locus): Adjust to use the
+ new public ordinary map interface.
+
+2011-10-16 Tristan Gingold <gingold@adacore.com>
+
+ * link.c (_AIX): Add support for GNU ld.
+
+2011-10-16 Fedor Rybin <frybin@adacore.com>
+
+ * gnat_ugn.texi: Fixing gnattest example names in the doc.
+ Adding explanation to additional tests usage.
+
+2011-10-16 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch6.adb, sem_ch6.adb: Minor reformatting.
+
+2011-10-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * a-convec.adb: Fix minor inconsistencies.
+
+2011-10-16 Matthew Heaney <heaney@adacore.com>
+
+ * a-cusyqu.ads, a-cbsyqu.ads, a-cuprqu.ads, a-cbprqu.ads (package
+ Implementation): Specify pragma Implementation_Defined.
+
+2011-10-15 Nicolas Roche <roche@adacore.com>
+
+ * gcc-interface/lang-specs.h: Ensure -mrtp switch is passed when using
+ either rtp-smp or ravenscar-cert-rtp runtimes.
+
+2011-10-15 Bob Duff <duff@adacore.com>
+
+ * exp_ch6.adb (Add_Unconstrained_Actuals_To_Build_In_Place_Call):
+ Do not create a pool formal on unless RE_Root_Storage_Pool_Ptr
+ is available.
+ (Expand_N_Extended_Return_Statement): Do not create a renaming of the
+ build-in-place pool parameter unless RE_Root_Storage_Pool_Ptr is
+ available.
+ (Make_Build_In_Place_Call_In_Allocator): Add the user-defined
+ pool only if RE_Root_Storage_Pool_Ptr is available.
+ (Make_Build_In_Place_Call_In_Object_Declaration): Do not add a
+ pool actual unless RE_Root_Storage_Pool_Ptr is available.
+ * sem_ch6.adb (Create_Extra_Formals): Add build-in-place pool
+ formal only if RE_Root_Storage_Pool_Ptr is available.
+
+2011-10-15 Matthew Heaney <heaney@adacore.com>
+
+ * a-cusyqu.ads, a-cbsyqu.ads, a-cuprqu.ads, a-cbprqu.ads (Queue
+ type): Specify Priority aspect for protected type.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_disp.adb (Check_Premature_Freezing): If an untagged type
+ is a generic actual, it is a subtype of a type that was frozen
+ by the instantiation, and even if not marked frozen it does not
+ affect the construction of the dispatch table.
+
+2011-10-14 Robert Dewar <dewar@adacore.com>
+
+ * make.adb, mlib-utl.adb, sem_util.adb, sem_ch4.adb: Minor code
+ reformatting.
+ * s-rident.ads: Add missing Compiler_Unit pragma.
+
+2011-10-14 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_res.adb: Minor reformatting.
+
+2011-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch6.adb (Add_Task_Actuals_To_Build_In_Place_Call):
+ Code and comment reformatting. Use BIP_Task_Master
+ when creating a _master.
+ (BIP_Formal_Suffix): Code reformatting. Correct the case for
+ BIP_Task_Master.
+ (Make_Build_In_Place_Call_In_Object_Declaration): Use
+ BIP_Task_Master when creating a reference to the enclosing
+ function's _master formal.
+ (Move_Activation_Chain): Use BIP_Task_Master when creating a reference
+ to the _master.
+ * exp_ch6.ads: Change BIP_Master to BIP_Task_Master.
+ (Needs_BIP_Finalization_Master): Alphabetized.
+ * sem_ch6.adb (Create_Extra_Formals): Update the usage of
+ BIP_Task_Master.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * par-ch6.adb (P_Return_Object_Declaration): In Ada 2012 mode,
+ reject an aliased keyword on the object declaration of an extended
+ return statement. In older versions of the language indicate
+ that this is illegal in the standard.
+
+2011-10-14 Pascal Obry <obry@adacore.com>
+
+ * sem_util.adb, sem_ch4.adb: Minor reformatting.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb: Recognize properly procedure calls that are
+ transformed into code statements.
+
+2011-10-14 Vincent Celier <celier@adacore.com>
+
+ * projects.texi: Minor fix in project example.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.adb: Return objects are aliased if their type is
+ immutably limited as per AI05-0053.
+
+2011-10-14 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Op_And): Remove Short_Circuit_And_Or
+ expansion code (moved to sem_res) (Expand_N_Op_Or): Remove
+ Short_Circuit_And_Or expansion code (moved to sem_res).
+ * sem_res.adb (Resolve_Logical_Op): Add code to rewrite Boolean
+ "and" and "or" operators as short-circuit "and then" and "or
+ else", when pragma Short_Circuit_And_Or is active.
+
+2011-10-13 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch9.adb, sem_util.adb, sem_util.ads, exp_ch6.adb, sem_ch4.adb,
+ sem_ch6.adb, exp_ch3.adb: Minor reformatting.
+
+2011-10-13 Arnaud Charlet <charlet@adacore.com>
+
+ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add a-ngcoar.o.
+
+2011-10-13 Jerome Guitton <guitton@adacore.com>
+
+ * sysdep.c (__gnat_get_task_options): Re-enable VX_SPE_TASK on vThreads
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * a-convec.ads (Cursor): Minor reformatting.
+ * a-convec.adb (Next): Fix minor inconsistencies.
+ (Previous): Likewise.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.ads, sem_util.adb (Available_Full_View_Of_Component):
+ New predicate to determine whether some operations on an array
+ type are available when the full view of its component may differ
+ from the view of the point of the array declaration.
+ * sem_ch4.adb (Find_Equality_Types): Use
+ Available_Full_View_Of_Component.
+ * sem_type.adb (Valid_Boolean_Arg, Valid_Comparison_Arg): Ditto
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch9.adb: Analyze aspects while discriminants of protected
+ type are visible.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * Makefile.rtl (GNATRTL_TASKING_OBJECTS): Add
+ a-nlcoar.o, a-nllcar.o, a-nucoar.o and s-gearop.o, as these no
+ longer depend on an external library.
+ * gcc-interface/Makefile.in (GNATRTL_LINEARALGEBRA_OBJS): Remove
+ a-nlcoar.o, a-nllcar.o, a-nucoar.o and s-gearop.o.
+ Update dependencies.
+ * gcc-interface/Make-lang.in: Update dependencies.
+
+2011-10-13 Cyrille Comar <comar@adacore.com>
+
+ * gnat_ugn.texi: Minor editing.
+
+2011-10-13 Vincent Celier <celier@adacore.com>
+
+ * projects.texi: Add documentation on packages and attributes
+ that are inherited from a project being extended into the
+ extended project.
+
+2011-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch3.adb (Build_Master): Rewritten.
+ (Expand_N_Full_Type_Declaration): Reformat the declarative
+ region. Update the call to Build_Master_Renaming.
+ (Expand_Previous_Access_Type): Rewritten.
+ * exp_ch6.adb (Add_Task_Actuals_To_Build_In_Place_Call):
+ Add local constant Result_Subt and update related usage.
+ (Expand_N_Extended_Return_Statement): Add local constant
+ Result_Subt and update related usage.
+ * exp_ch9.adb (Build_Activation_Chain): Rewritten to use the
+ new context detection mechanism.
+ (Build_Class_Wide_Master):
+ Use Insert_Action to add the renaming into the tree.
+ (Build_Master_Entity): Rewritten to use the new context detection
+ mechanism.
+ (Build_Master_Renaming): Add formal parameter Ins_Nod
+ and related usage. Use Insert_Action to add the renaming into the
+ tree.
+ (Find_Enclosing_Context): New subsidiary routine. Rather
+ than relying on enclosing scopes, this routine looks at the
+ tree structure to figure out the proper context for a _master
+ or a _chain. This approach eliminates the issues with transient
+ scopes which have not been converted into blocks.
+ * exp_ch9.ads (Build_Master_Entity): Change parameter profile
+ to better reflect the new usage. Update the related comment.
+ (Build_Master_Renaming): Add formal parameter Ins_Nod. Update
+ the comment on usage.
+ * sem_ch3.adb (Access_Definition): Update the calls to
+ Build_Master_Entity and Build_Master_Renaming.
+ * sem_ch6.adb (Create_Extra_Formals): Add local variable
+ Full_Subt. Code reformatting.
+ * sem_util.adb (Is_Iterator): Alphabetized.
+ (Is_LHS): Alphabetized.
+ (Is_Limited_Class_Wide_Type): New routine.
+ * sem_util.ads (Is_Limited_Class_Wide_Type): New routine.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * a-ngrear.adb (Solve): Make generic and move to
+ System.Generic_Array_Operations.
+ * s-gearop.ads (Matrix_Vector_Solution, Matrix_Matrix_Solution):
+ New generic solvers to compute a vector resp. matrix Y such
+ that A * Y = X, approximately.
+ * s-gearop.adb (Matrix_Vector_Solution, Matrix_Matrix_Solution):
+ Implement using Forward_Eliminate and Back_Substitute
+ * a-ngcoar.adb: Reimplement in pure Ada to remove dependencies
+ on BLAS and LAPACK.
+ * a-ngcoar.ads ("abs"): Fix return type to be real.
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/50589
+ * s-linux-alpha.ads: Do not "with" Interfaces.C.
+ * s-linux-sparc.ads: Likewise.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * s-gearop.ads (Forward_Eliminate): Add "abs" formal function
+ returning a Real.
+ * s-gearop.adb (Forward_Eliminate): Remove local "abs" function
+ and use formal.
+ * a-ngrear.adb (Forward_Eliminate): Adjust instantiation for
+ new profile.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * a-ngrear.adb, s-gearop.adb, s-gearop.ads (Sqrt): Make generic and
+ move to System.Generic_Array_Operations.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * a-ngrear.adb ("abs"): Adjust for modified L2_Norm generic
+ * s-gearop.ads (L2_Norm): Change profile to be suitable for
+ Complex_Vector
+ * s-gearop.adb (L2_Norm): Reimplement using direct definition,
+ not inner product
+
+2011-10-13 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch5.adb, sem_ch3.adb, impunit.adb, impunit.ads, sem_type.adb,
+ prj-proc.adb, exp_ch9.adb, s-regpat.adb, sem_ch10.adb, sem_prag.adb,
+ sem_ch12.adb, freeze.adb, sem_attr.adb, sem_attr.ads, gnatlink.adb,
+ par-ch6.adb, exp_ch6.adb, sem_ch4.adb, sem_ch6.adb, sem_ch8.adb,
+ par-util.adb, sem_ch13.adb, lib-xref.adb, g-trasym.adb, g-trasym.ads,
+ exp_aggr.adb, s-taprop-posix.adb: Minor reformatting.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * s-gearop.adb: Minor comment additions.
+
+2011-10-13 Fedor Rybin <frybin@adacore.com>
+
+ * gnat_ugn.texi: Add gnattest section.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb: Do not create body of renaming if declaration has
+ errors.
+
+2011-10-13 Olivier Hainque <hainque@adacore.com>
+
+ * init.c (__gnat_error_handler - vxworks case): Restrict sigtramp calls
+ further, to the ppc+kernel case only.
+
+2011-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Allocator): Comment reformatting.
+ * exp_ch6.adb (Add_Unconstrained_Actuals_To_Build_In_Place_Call):
+ Do not create a pool formal on .NET/JVM.
+ (Expand_N_Extended_Return_Statement): Alphabetize local
+ variables. Do not create a renaming of the build-in-place pool
+ parameter on .NET/JVM. (Make_Build_In_Place_Call_In_Allocator):
+ Add the user-defined pool only on non-VM targets.
+ (Make_Build_In_Place_Call_In_Object_Declaration): Alphabetize
+ local variables. Do not add a pool actual on .NET/JVM.
+ * sem_ch6.adb: Add with and use clause for Targparm.
+ (Create_Extra_Formals): Add build-in-place pool formal only on
+ non-VM targets.
+ * rtsfind.ads: Alphabetize entries.
+
+2011-10-13 Sergey Rybin <rybin@adacore.com>
+
+ * gnat_ugn.texi: Minor correction.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch8.adb: Minor error message improvement.
+
+2011-10-13 Robert Dewar <dewar@adacore.com>
+
+ * a-cbprqu.adb, a-ciorma.adb, exp_ch3.adb: Minor reformatting.
+
+2011-10-13 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_ch5.adb (Expand_N_Loop_Statement): For the transformation
+ of a for loop for an enumeration type with an enumeration rep
+ clause, which involves moving the original loop parameter into
+ a nested block, the loop parameter's entity must be removed from
+ the entity list of the loop scope.
+
+2011-10-13 Bob Duff <duff@adacore.com>
+
+ * exp_ch6.ads (BIP_Storage_Pool): New "extra implicit parameter"
+ that gets passed in the same cases where BIP_Alloc_Form is passed
+ (caller-unknown-size results). BIP_Storage_Pool is used when
+ BIP_Alloc_Form = User_Storage_Pool. In that case, a pointer
+ to the user-defined storage pool is passed at the call site,
+ and this pool is used in callee to allocate the result.
+ * exp_ch6.adb (Add_Unconstrained_Actuals_To_Build_In_Place_Call): New
+ version of Add_Alloc_Form_Actual_To_Build_In_Place_Call. Passes
+ the additional BIP_Storage_Pool actual.
+ (Expand_N_Extended_Return_Statement): Allocate the function
+ result using the user-defined storage pool, if BIP_Alloc_Form =
+ User_Storage_Pool.
+ * sem_ch6.adb: Add the "extra formal" for BIP_Storage_Pool.
+ * exp_ch4.adb: Don't overwrite storage pool set by
+ Expand_N_Extended_Return_Statement.
+ * s-stopoo.ads, rtsfind.ads (Root_Storage_Pool_Ptr): New type,
+ for use in build-in-place function calls within allocators
+ where the access type has a user-defined storage pool.
+
+2011-10-13 Sergey Rybin <rybin@adacore.com>
+
+ * gnat_ugn.texi, vms_data.ads: Add an option to control enumeration
+ literal casing.
+
+2011-10-13 Nicolas Roche <roche@adacore.com>
+
+ * gnatlink.adb: Ensure that -mrtp is passed when
+ runtime name ends with 'rtp'.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma, case Unchecked_Union): an
+ unchecked union type can be limited.
+
+2011-10-13 Olivier Hainque <hainque@adacore.com>
+
+ * init.c (__gnat_error_handler) <VxWorks version>: Add comments on
+ the use of the signal trampoline for PPC in the sjlj case as well.
+ Add legitimate casts, preventing compile time warnings on the
+ (sighandler *) profile.
+
+2011-10-13 Yannick Moy <moy@adacore.com>
+
+ * sem_aggr.adb (Resolve_Aggr_Expr): Always perform semantic
+ analysis in Alfa mode.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (OK_For_Limited_Init_In_05): Conditional and case
+ expressions are legal limited return values if each one of their
+ dependent expressions are legal.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Analyze_Procedure_Call_Statement): In Ada 2012 mode,
+ if the prefix of the call is a qualified expression, rewrite as
+ a code statement.
+ * sem_ch13.adb (Analyze_Code_Statement): In Ada 2012 mode, the
+ code statement is legal if it is a rewriting of a procedure call.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Flatten): If a component association has a box,
+ assume that aggregate is not static.
+ (Safe_Aggregate): If a component association in a non-limited
+ aggregate has a box, assume that it cannot be expanded in place.
+
+2011-10-13 Vincent Celier <celier@adacore.com>
+
+ * prj-conf.adb (Get_Or_Create_Configuration_File): Call
+ Process_Project_Tree_Phase_1 with Packages_To_Check.
+ (Process_Project_And_Apply_Config): Ditto
+ * prj-part.ads, prj-part.adb, prj-pars.ads, prj-pars.adb (Parse):
+ Remove default for argument Packages_To_Check.
+ * prj-proc.adb (Recursive_Process): New argument
+ Packages_To_Check.
+ (Process): Ditto.
+ (Process_Project_Tree_Phase_1): Ditto.
+ (Recursive_Project.Process_Aggregated_Projects): Call
+ Prj.Part.Parse and Process_Project_Tree_Phase_1 with
+ Packages_To_Check.
+ * prj-proc.ads (Process): New argument Packages_To_Check
+ (Process_Project_Tree_Phase_1): Ditto
+
+2011-10-13 Arnaud Charlet <charlet@adacore.com>
+
+ * gcc-interface/Makefile.in: Fix typo.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Analyze_Formal_{Floating_Type,
+ Signed_Integer_Type, Decimal_Fixed_Point_Type, Discrete_Type}):
+ Use sloc of defining identifier of farmal type declaration,
+ as sloc of generated internal entity, to prevent misplaced
+ references in ali.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_intr.adb (Check_Intrinsic_Operator): Check that type
+ is fully defined before checking that it is a numeric type.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aggr.adb (Resolve_Record_Aggregate): If a component
+ association for component X has a box, then X is covered in the
+ aggregate even if there is not default value for X in the type
+ declaration, and X has to be default-initialized.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb (Check_Enum_Image, Analyze_Attribute case
+ 'Value): Mark literals as referenced only if reference is in
+ current source unit.
+
+2011-10-13 Matthew Heaney <heaney@adacore.com>
+
+ * a-csquin.ads (Enque, Dequeue): Mark interface operations as entries.
+
+2011-10-13 Olivier Hainque <hainque@adacore.com>
+
+ * sigtramp.h: New file. Prototype and spec of the signal
+ trampoline to be called by an established handler to provide
+ dwarf call frame info before the real signal processing code.
+ * sigtramp-ppcvxw.c: New file. Implementation of the signal
+ trampoline for ppc-vxworks.
+ * init.c (vxworks section): Use it for ppc.
+
+2011-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * par-ch2.adb, par.adb, par-util.adb, par-ch3.adb
+ (Check_Future_Identifier): New subprogram,
+ factors duplicated code from Par.Ch2.P_Identifier and
+ Par.Ch3.P_Defining_Identifier.
+
+2011-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * s-taprop-posix.adb (Initialize): Always raise Storage_Error
+ if we fail to initialize CV attributes or CV.
+
+2011-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * s-tasren.adb (Timed_Selective_Wait, case
+ Accept_Alternative_Selected): Use Defer_Abort_Nestable, since
+ we know abortion is already deferred.
+
+2011-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch3.adb (Build_Class_Wide_Master): Moved to exp_ch9.
+ (Build_Master_Renaming (function)): Removed.
+ (Build_Master_Renaming (procedure)): Moved to exp_ch9.
+ (Expand_Full_Type_Declaration): Alphabetize
+ variables. Reformatting of code and comments. Rewrite the
+ section on processing of anonymous access-to-task types in
+ record components.
+ * exp_ch3.ads (Build_Class_Wide_Master): Moved to exp_ch9.
+ (Build_Master_Renaming): Moved to exp_ch9.
+ * exp_ch9.adb (Build_Class_Wide_Master): Moved from exp_ch3.
+ (Build_Master_Entity): Add formal parameter
+ Use_Current. Reformatting of code and comments.
+ (Build_Master_Renaming): Moved from exp_ch3.
+ * exp_ch9.ads (Build_Class_Wide_Master): Moved from
+ exp_ch3. Update comment on usage.
+ (Build_Master_Entity):
+ Add formal parameter Use_Current. Update comment on usage.
+ (Build_Master_Renaming): Moved from exp_ch3.
+ * sem_ch3.adb (Access_Definition): Remove redundant code to
+ create a _master and a renaming.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * lib-xref.adb: Do no emit reference to overridden operation,
+ if it is internally generated.
+
+2011-10-13 Vincent Celier <celier@adacore.com>
+
+ * bindgen.adb: Remove any processing related to g-trasym
+ * Makefile.rtl: Add g-trasym.o to GNATRTL_NONTASKING_OBJS
+ * mlib-prj.adb: Remove any processing related to g-trasym.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_util.adb (Denotes_Same_Prefix): Fix fatal warning.
+ * gcc-interface/Make-lang.in (WARN_ADAFLAGS): New.
+ (ALL_ADAFLAGS): Include WARN_ADAFLAGS.
+ (ADA_FLAGS_TO_PASS): Likewise.
+ (COMMON_FLAGS_TO_PASS): New.
+ (ADA_TOOLS_FLAGS_TO_PASS): Use COMMON_FLAGS_TO_PASS. In the regular
+ native case, also use FLAGS_TO_PASS and ADA_FLAGS_TO_PASS.
+ (gnatlib): Use COMMON_FLAGS_TO_PASS.
+ (ada.install-common): Likewise.
+ (install-gnatlib): Likewise.
+ (install-gnatlib-obj): Likewise.
+ (gnattools): Use ADA_TOOLS_FLAGS_TO_PASS for gnattools1 as well.
+ (gnat-cross): Delete.
+ (gnatboot): Likewise.
+ (gnatboot2): Likewise.
+ (gnatboot3): Likewise.
+ (gnatstage1): Likewise.
+ (gnatstage2): Likewise.
+ * gcc-interface/Makefile.in (SOME_ADAFLAGS): Likewise.
+ (MOST_ADAFLAGS): Likewise.
+ (LOOSE_CFLAGS): Likewise.
+ (gnat-cross): Likewise.
+ (GNATLIBFLAGS): Add -W -Wall.
+ (GNATLIBCFLAGS_FOR_C): Likewise.
+ * gcc-interface/lang.opt: Remove C-specific warnings. Add doc lines.
+ * gcc-interface/misc.c (gnat_handle_option): Remove obsolete cases.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Attribute_to_gnu): Use remove_conversions.
+ (push_range_check_info): Likewise.
+ (gnat_to_gnu) <N_Code_Statement>: Likewise.
+ * gcc-interface/utils2.c (build_unary_op) <INDIRECT_REF>: Likewise.
+ (gnat_invariant_expr): Likewise.
+ * gcc-interface/utils.c (compute_related_constant): Likewise.
+ (max_size): Fix handling of SAVE_EXPR.
+ (remove_conversions): Fix formatting.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/ada-tree.h (DECL_LOOP_PARM_P): New flag.
+ (DECL_INDUCTION_VAR): New macro.
+ (SET_DECL_INDUCTION_VAR): Likewise.
+ * gcc-interface/gigi.h (convert_to_index_type): Declare.
+ (gnat_invariant_expr): Likewise.
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: If this is a loop
+ parameter, set DECL_LOOP_PARM_P on it.
+ * gcc-interface/misc.c (gnat_print_decl) <VAR_DECL>: If DECL_LOOP_PARM_P
+ is set, print DECL_INDUCTION_VAR instead of DECL_RENAMED_OBJECT.
+ * gcc-interface/trans.c (gnu_loop_label_stack): Delete.
+ (struct range_check_info_d): New type.
+ (struct loop_info_d): Likewise.
+ (gnu_loop_stack): New stack.
+ (Identifier_to_gnu): Set TREE_READONLY flag on the first dereference
+ built for a by-double-ref read-only parameter. If DECL_LOOP_PARM_P
+ is set, do not test DECL_RENAMED_OBJECT.
+ (push_range_check_info): New function.
+ (Loop_Statement_to_gnu): Push a new struct loop_info_d instead of just
+ the label. Reference the label and the iteration variable from it.
+ Build the special induction variable in the unsigned version of the
+ size type, if it is larger than the base type. And attach it to the
+ iteration variable if the latter isn't by-ref. In the iteration scheme
+ case, initialize the invariant conditions in front of the loop if
+ deemed profitable. Use gnu_loop_stack.
+ (gnat_to_gnu) <N_Exit_Statement>: Use gnu_loop_stack.
+ <N_Raise_Constraint_Error>: Always process the reason. In the range
+ check and related cases, and if loop unswitching is enabled, compute
+ invariant conditions and push this information onto the stack.
+ Do not translate again the condition if it has been already translated.
+ * gcc-interface/utils.c (record_global_renaming_pointer): Assert that
+ DECL_LOOP_PARM_P isn't set.
+ (convert_to_index_type): New function.
+ * gcc-interface/utils2.c (build_binary_op) <ARRAY_REF>: Use it in order
+ to convert the index from the base index type to sizetype.
+ (gnat_invariant_expr): New function.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc-interface/utils.c (def_builtin_1): Delete old interface with
+ two parallel arrays to hold standard builtin declarations, and
+ replace it with a function based interface that can support
+ creating builtins on the fly in the future.
+ * gcc-interface/trans.c (Exception_Handler_to_gnu_zcx): Ditto.
+ (gnat_to_gnu): Ditto.
+
+2011-10-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR lto/50492
+ * gcc-interface/gigi.h (gnat_pushdecl): Adjust comment.
+ * gcc-interface/utils.c (global_context): New variable.
+ (gnat_pushdecl): Initialize it and set it as the DECL_CONTEXT of DECLs
+ that are either public external or at top level. Use "No" macro.
+ (end_subprog_body): Call decl_function_context.
+ (rest_of_subprog_body_compilation): Likewise.
+
+2011-10-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/gigi.h (gnat_useless_type_conversion): Declare.
+ (rest_of_subprog_body_compilation): Likewise.
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Variable>: For renaming,
+ test for useless conversions by means of gnat_useless_type_conversion.
+ * gcc-interface/trans.c: Include bitmap.h and cgraph.h.
+ (language_function): Add named_ret_val and other_ret_val.
+ (f_named_ret_val): New macro.
+ (f_other_ret_val): Likewise.
+ (gigi): Call rest_of_subprog_body_compilation.
+ (struct nrv_data): New structure.
+ (is_nrv_p): New predicate.
+ (prune_nrv_r): New helper function.
+ (prune_nrv_in_block): New function.
+ (finalize_nrv_r): New helper function.
+ (finalize_nrv): New function.
+ (return_value_ok_for_nrv_p): New predicate.
+ (build_return_expr): If optimization is enabled, record candidates for
+ the Named Return Value optimization.
+ (build_function_stub): Call rest_of_subprog_body_compilation.
+ (Subprogram_Body_to_gnu): If optimization is enabled and there are
+ candidates, finalize the Named Return Value optimization.
+ Call rest_of_subprog_body_compilation.
+ (call_to_gnu): At the end, if a return value is needed, simplify the
+ result before wrapping it up in a COMPOUND_EXPR.
+ * gcc-interface/utils.c (end_subprog_body): Split into...
+ (rest_of_subprog_body_compilation): ...this. New function.
+ (gnat_useless_type_conversion): Likewise.
+
+2011-10-06 Thomas Quinot <quinot@adacore.com>
+
+ * einfo.ads, exp_attr.adb, exp_ch3.adb, exp_ch4.adb, exp_ch7.adb,
+ exp_ch9.adb, exp_ch9.ads, exp_strm.adb, exp_util.adb, freeze.adb,
+ g-debpoo.ads, opt.ads, par-ch12.adb, par-ch2.adb, par-ch3.adb,
+ par-ch5.adb, par-ch6.adb, sem_aggr.adb, sem_attr.adb, sem_cat.adb,
+ sem_ch10.adb, sem_ch12.adb, sem_ch3.adb, sem_ch4.adb, sem_ch5.adb,
+ sem_ch6.adb, sem_intr.adb, sem_res.ads, sem_type.adb, sem_util.adb,
+ s-regpat.adb, s-tpopde-vms.ads: Minor reformatting.
+ * s-osinte-freebsd.ads: Fix for tasking failures on FreeBSD.
+
+2011-10-06 Ed Schonberg <schonberg@adacore.com>
+
+ * a-cihase.adb, a-ciorma.adb: Avoid accessibility checks in container
+ references.
+
+2011-10-06 Matthew Heaney <heaney@adacore.com>
+
+ * a-cuprqu.ads, a-cuprqu.adb, a-cbprqu.ads, a-cbprqu.adb
+ (Dequeue_Only_High_Priority): Protected procedure now implemented.
+
+2011-10-06 Vincent Celier <celier@adacore.com>
+
+ * g-trasym.adb: Replace old implementation with the default
+ implementation that returns list of addresses as "0x...".
+ * g-trasym.ads: Update the list of platforms with the full
+ capability. Indicate that there is a default implementation
+ for other platforms.
+ * g-trasym-unimplemented.ads, g-trasym-unimplemented.adb: Remove.
+ * gcc-interface/Makefile.in: Remove g-trasym-unimplemented, as there
+ is now a default implementation for all platforms without the full
+ capability.
+
+2011-10-06 Robert Dewar <dewar@adacore.com>
+
+ * a-ciorse.adb, a-cihase.adb, a-cihase.ads, a-coorse.adb,
+ a-cborse.adb, a-comutr.adb, a-ciorma.adb, a-cbmutr.adb,
+ a-cbmutr.ads, a-cbhase.adb, a-cbhase.ads: Minor reformatting and code
+ reorganization (use conditional expressions).
+
+2011-10-06 Robert Dewar <dewar@adacore.com>
+
+ * sem_res.adb (Resolve_Arithmetic_Op): Fix bad warning for
+ floating divide by zero.
+
+2011-10-06 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb: Limited interfaces that are not immutably limited
+ are OK in return statements.
+
2011-09-30 Iain Sandoe <iains@gcc.gnu.org>
* gcc-interface/Makefile.in (Darwin): Partial reversion of previous
@@ -8621,15 +9295,16 @@
2011-08-03 Matthew Heaney <heaney@adacore.com>
- * a-cobove.adb (Merge): Move source onto target, instead of using Assign
+ * a-cobove.adb (Merge): Move source onto target, instead of using
+ Assign.
2011-08-03 Matthew Heaney <heaney@adacore.com>
- * a-cbdlli.adb (Splice): move source items from first to last
+ * a-cbdlli.adb (Splice): Move source items from first to last.
2011-08-03 Yannick Moy <moy@adacore.com>
- * sem_util.ads: comment added.
+ * sem_util.ads: Add comment.
2011-08-03 Javier Miranda <miranda@adacore.com>
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 30a95065153..4e03c9e178e 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -186,27 +186,31 @@ GNATRTL_NONTASKING_OBJS= \
a-locale$(objext) \
a-ncelfu$(objext) \
a-ngcefu$(objext) \
+ a-ngcoar$(objext) \
a-ngcoty$(objext) \
a-ngelfu$(objext) \
a-ngrear$(objext) \
- a-nllrar$(objext) \
- a-nlrear$(objext) \
- a-nurear$(objext) \
a-nlcefu$(objext) \
+ a-nlcoar$(objext) \
a-nlcoty$(objext) \
a-nlelfu$(objext) \
+ a-nlrear$(objext) \
+ a-nllcar$(objext) \
a-nllcef$(objext) \
a-nllcty$(objext) \
a-nllefu$(objext) \
+ a-nllrar$(objext) \
a-nscefu$(objext) \
a-nscoty$(objext) \
a-nselfu$(objext) \
+ a-nucoar$(objext) \
a-nucoty$(objext) \
a-nudira$(objext) \
a-nuelfu$(objext) \
a-nuflra$(objext) \
a-numaux$(objext) \
a-numeri$(objext) \
+ a-nurear$(objext) \
a-rbtgbo$(objext) \
a-rbtgbk$(objext) \
a-rbtgso$(objext) \
@@ -435,6 +439,7 @@ GNATRTL_NONTASKING_OBJS= \
g-tasloc$(objext) \
g-timsta$(objext) \
g-traceb$(objext) \
+ g-trasym$(objext) \
g-u3spch$(objext) \
g-utf_32$(objext) \
g-wispch$(objext) \
@@ -514,6 +519,7 @@ GNATRTL_NONTASKING_OBJS= \
s-fvadfl$(objext) \
s-fvaffl$(objext) \
s-fvagfl$(objext) \
+ s-gearop$(objext) \
s-geveop$(objext) \
s-gloloc$(objext) \
s-htable$(objext) \
diff --git a/gcc/ada/a-cbhase.adb b/gcc/ada/a-cbhase.adb
index 7dcd074995d..97a765a6839 100644
--- a/gcc/ada/a-cbhase.adb
+++ b/gcc/ada/a-cbhase.adb
@@ -47,7 +47,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
overriding function First (Object : Iterator) return Cursor;
overriding function Next
- (Object : Iterator;
+ (Object : Iterator;
Position : Cursor) return Cursor;
-----------------------
@@ -68,9 +68,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
Node : out Count_Type;
Inserted : out Boolean);
- function Is_In
- (HT : Set;
- Key : Node_Type) return Boolean;
+ function Is_In (HT : Set; Key : Node_Type) return Boolean;
pragma Inline (Is_In);
procedure Set_Element (Node : in out Node_Type; Item : Element_Type);
@@ -169,7 +167,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
N : Node_Type renames Source.Nodes (Source_Node);
X : Count_Type;
B : Boolean;
-
begin
Insert (Target, N.Element, X, B);
pragma Assert (B);
@@ -233,10 +230,8 @@ package body Ada.Containers.Bounded_Hashed_Sets is
begin
if Capacity = 0 then
C := Source.Length;
-
elsif Capacity >= Source.Length then
C := Capacity;
-
else
raise Capacity_Error with "Capacity value too small";
end if;
@@ -396,7 +391,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
N : Node_Type renames Left.Nodes (L_Node);
X : Count_Type;
B : Boolean;
-
begin
if not Is_In (Right, N) then
Insert (Result, N.Element, X, B); -- optimize this ???
@@ -428,7 +422,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
declare
S : Set renames Position.Container.all;
N : Node_Type renames S.Nodes (Position.Node);
-
begin
return N.Element;
end;
@@ -488,6 +481,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
function Equivalent_Elements (Left, Right : Cursor)
return Boolean is
+
begin
if Left.Node = 0 then
raise Constraint_Error with
@@ -505,14 +499,15 @@ package body Ada.Containers.Bounded_Hashed_Sets is
declare
LN : Node_Type renames Left.Container.Nodes (Left.Node);
RN : Node_Type renames Right.Container.Nodes (Right.Node);
-
begin
return Equivalent_Elements (LN.Element, RN.Element);
end;
end Equivalent_Elements;
- function Equivalent_Elements (Left : Cursor; Right : Element_Type)
- return Boolean is
+ function Equivalent_Elements
+ (Left : Cursor;
+ Right : Element_Type) return Boolean
+ is
begin
if Left.Node = 0 then
raise Constraint_Error with
@@ -528,8 +523,10 @@ package body Ada.Containers.Bounded_Hashed_Sets is
end;
end Equivalent_Elements;
- function Equivalent_Elements (Left : Element_Type; Right : Cursor)
- return Boolean is
+ function Equivalent_Elements
+ (Left : Element_Type;
+ Right : Cursor) return Boolean
+ is
begin
if Right.Node = 0 then
raise Constraint_Error with
@@ -551,8 +548,10 @@ package body Ada.Containers.Bounded_Hashed_Sets is
-- Equivalent_Keys --
---------------------
- function Equivalent_Keys (Key : Element_Type; Node : Node_Type)
- return Boolean is
+ function Equivalent_Keys
+ (Key : Element_Type;
+ Node : Node_Type) return Boolean
+ is
begin
return Equivalent_Elements (Key, Node.Element);
end Equivalent_Keys;
@@ -580,13 +579,9 @@ package body Ada.Containers.Bounded_Hashed_Sets is
Item : Element_Type) return Cursor
is
Node : constant Count_Type := Element_Keys.Find (Container, Item);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
-----------
@@ -595,23 +590,16 @@ package body Ada.Containers.Bounded_Hashed_Sets is
function First (Container : Set) return Cursor is
Node : constant Count_Type := HT_Ops.First (Container);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end First;
overriding function First (Object : Iterator) return Cursor is
Node : constant Count_Type := HT_Ops.First (Object.Container.all);
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Object.Container, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Object.Container, Node));
end First;
-----------------
@@ -999,11 +987,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
"Position cursor designates wrong set";
end if;
- if Position.Node = 0 then
- return No_Element;
- end if;
-
- return Next (Position);
+ return (if Position.Node = 0 then No_Element else Next (Position));
end Next;
-------------
@@ -1143,12 +1127,10 @@ package body Ada.Containers.Bounded_Hashed_Sets is
(Container : aliased Set;
Position : Cursor) return Constant_Reference_Type
is
+ pragma Unreferenced (Container);
S : Set renames Position.Container.all;
N : Node_Type renames S.Nodes (Position.Node);
-
begin
- pragma Unreferenced (Container);
-
return (Element => N.Element'Unrestricted_Access);
end Constant_Reference;
@@ -1316,7 +1298,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
N : Node_Type renames Left.Nodes (L_Node);
X : Count_Type;
B : Boolean;
-
begin
if not Is_In (Right, N) then
Insert (Result, N.Element, X, B);
@@ -1344,7 +1325,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
N : Node_Type renames Right.Nodes (R_Node);
X : Count_Type;
B : Boolean;
-
begin
if not Is_In (Left, N) then
Insert (Result, N.Element, X, B);
@@ -1367,7 +1347,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
function To_Set (New_Item : Element_Type) return Set is
X : Count_Type;
B : Boolean;
-
begin
return Result : Set (1, 1) do
Insert (Result, New_Item, X, B);
@@ -1396,7 +1375,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
N : Node_Type renames Source.Nodes (Src_Node);
X : Count_Type;
B : Boolean;
-
begin
Insert (Target, N.Element, X, B);
end Process;
@@ -1413,7 +1391,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
"attempt to tamper with cursors (set is busy)";
end if;
- -- ???
+ -- ??? why is this code commented out ???
-- declare
-- N : constant Count_Type := Target.Length + Source.Length;
-- begin
@@ -1661,15 +1639,10 @@ package body Ada.Containers.Bounded_Hashed_Sets is
(Container : Set;
Key : Key_Type) return Cursor
is
- Node : constant Count_Type :=
- Key_Keys.Find (Container, Key);
-
+ Node : constant Count_Type := Key_Keys.Find (Container, Key);
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
---------
@@ -1684,7 +1657,6 @@ package body Ada.Containers.Bounded_Hashed_Sets is
end if;
pragma Assert (Vet (Position), "bad cursor in function Key");
-
return Key (Position.Container.Nodes (Position.Node).Element);
end Key;
@@ -1697,8 +1669,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
Key : Key_Type;
New_Item : Element_Type)
is
- Node : constant Count_Type :=
- Key_Keys.Find (Container, Key);
+ Node : constant Count_Type := Key_Keys.Find (Container, Key);
begin
if Node = 0 then
@@ -1733,7 +1704,7 @@ package body Ada.Containers.Bounded_Hashed_Sets is
"Position cursor designates wrong set";
end if;
- -- ???
+ -- ??? why is this code commented out ???
-- if HT.Buckets = null
-- or else HT.Buckets'Length = 0
-- or else HT.Length = 0
@@ -1747,7 +1718,8 @@ package body Ada.Containers.Bounded_Hashed_Sets is
(Vet (Position),
"bad cursor in Update_Element_Preserving_Key");
- -- Record bucket now, in case key is changed.
+ -- Record bucket now, in case key is changed
+
Indx := HT_Ops.Index (Container.Buckets, N (Position.Node));
declare
@@ -1823,10 +1795,10 @@ package body Ada.Containers.Bounded_Hashed_Sets is
function Reference_Preserving_Key
(Container : aliased in out Set;
- Key : Key_Type) return Reference_Type
+ Key : Key_Type) return Reference_Type
is
Position : constant Cursor := Find (Container, Key);
- N : Node_Type renames Container.Nodes (Position.Node);
+ N : Node_Type renames Container.Nodes (Position.Node);
begin
return (Element => N.Element'Unrestricted_Access);
end Reference_Preserving_Key;
diff --git a/gcc/ada/a-cbhase.ads b/gcc/ada/a-cbhase.ads
index c72b8ab8597..3f6b6696871 100644
--- a/gcc/ada/a-cbhase.ads
+++ b/gcc/ada/a-cbhase.ads
@@ -148,8 +148,7 @@ package Ada.Containers.Bounded_Hashed_Sets is
function Constant_Reference
(Container : aliased Set;
- Position : Cursor)
- return Constant_Reference_Type;
+ Position : Cursor) return Constant_Reference_Type;
procedure Assign (Target : in out Set; Source : Set);
-- If Target denotes the same object as Source, then the operation has no
@@ -355,8 +354,9 @@ package Ada.Containers.Bounded_Hashed_Sets is
Process : not null access procedure (Position : Cursor));
-- Calls Process for each node in the set
- function Iterate (Container : Set)
- return Set_Iterator_Interfaces.Forward_Iterator'Class;
+ function Iterate
+ (Container : Set)
+ return Set_Iterator_Interfaces.Forward_Iterator'Class;
generic
type Key_Type (<>) is private;
@@ -431,13 +431,11 @@ package Ada.Containers.Bounded_Hashed_Sets is
function Reference_Preserving_Key
(Container : aliased in out Set;
- Position : Cursor)
- return Reference_Type;
+ Position : Cursor) return Reference_Type;
function Reference_Preserving_Key
(Container : aliased in out Set;
- Key : Key_Type)
- return Reference_Type;
+ Key : Key_Type) return Reference_Type;
private
type Reference_Type (Element : not null access Element_Type)
@@ -446,7 +444,6 @@ package Ada.Containers.Bounded_Hashed_Sets is
end Generic_Keys;
private
-
pragma Inline (Next);
type Node_Type is record
@@ -519,6 +516,6 @@ private
for Constant_Reference_Type'Write use Write;
Empty_Set : constant Set :=
- (Hash_Table_Type with Capacity => 0, Modulus => 0);
+ (Hash_Table_Type with Capacity => 0, Modulus => 0);
end Ada.Containers.Bounded_Hashed_Sets;
diff --git a/gcc/ada/a-cbmutr.adb b/gcc/ada/a-cbmutr.adb
index f4bdc5e4035..7ad2de4e62a 100644
--- a/gcc/ada/a-cbmutr.adb
+++ b/gcc/ada/a-cbmutr.adb
@@ -54,11 +54,11 @@ package body Ada.Containers.Bounded_Multiway_Trees is
overriding function First (Object : Child_Iterator) return Cursor;
overriding function Next
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor;
overriding function Previous
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor;
overriding function Last (Object : Child_Iterator) return Cursor;
@@ -599,10 +599,8 @@ package body Ada.Containers.Bounded_Multiway_Trees is
begin
if Capacity = 0 then
C := Source.Count;
-
elsif Capacity >= Source.Count then
C := Capacity;
-
else
raise Capacity_Error with "Capacity value too small";
end if;
@@ -841,12 +839,12 @@ package body Ada.Containers.Bounded_Multiway_Trees is
-- nodes that contain elements that have been inserted onto the tree,
-- and another for the "inactive" nodes of the free store, from which
-- nodes are allocated when a new child is inserted in the tree.
- --
+
-- We desire that merely declaring a tree object should have only
-- minimal cost; specially, we want to avoid having to initialize the
-- free store (to fill in the links), especially if the capacity of the
-- tree object is large.
- --
+
-- The head of the free list is indicated by Container.Free. If its
-- value is non-negative, then the free store has been initialized in
-- the "normal" way: Container.Free points to the head of the list of
@@ -854,20 +852,20 @@ package body Ada.Containers.Bounded_Multiway_Trees is
-- empty. Each node on the free list has been initialized to point to
-- the next free node (via its Next component), and the value 0 means
-- that this is the last node of the free list.
- --
+
-- If Container.Free is negative, then the links on the free store have
-- not been initialized. In this case the link values are implied: the
-- free store comprises the components of the node array started with
-- the absolute value of Container.Free, and continuing until the end of
-- the array (Nodes'Last).
- --
+
-- We prefer to lazy-init the free store (in fact, we would prefer to
-- not initialize it at all, because such initialization is an O(n)
-- operation). The time when we need to actually initialize the nodes in
-- the free store is when the node that becomes inactive is not at the
-- end of the active list. The free store would then be discontigous and
-- so its nodes would need to be linked in the traditional way.
- --
+
-- It might be possible to perform an optimization here. Suppose that
-- the free store can be represented as having two parts: one comprising
-- the non-contiguous inactive nodes linked together in the normal way,
@@ -1218,8 +1216,8 @@ package body Ada.Containers.Bounded_Multiway_Trees is
Right_Subtree : Count_Type) return Boolean
is
begin
- if Left_Tree.Elements (Left_Subtree)
- /= Right_Tree.Elements (Right_Subtree)
+ if Left_Tree.Elements (Left_Subtree) /=
+ Right_Tree.Elements (Right_Subtree)
then
return False;
end if;
@@ -1262,7 +1260,6 @@ package body Ada.Containers.Bounded_Multiway_Trees is
function First (Object : Child_Iterator) return Cursor is
Node : Count_Type'Base;
-
begin
Node := Object.Container.Nodes (Object.Position.Node).Children.First;
return (Object.Container, Node);
@@ -1722,11 +1719,9 @@ package body Ada.Containers.Bounded_Multiway_Trees is
function Is_Root (Position : Cursor) return Boolean is
begin
- if Position.Container = null then
- return False;
- end if;
-
- return Position.Node = Root_Node (Position.Container.all);
+ return
+ (if Position.Container = null then False
+ else Position.Node = Root_Node (Position.Container.all));
end Is_Root;
-------------
@@ -1839,7 +1834,7 @@ package body Ada.Containers.Bounded_Multiway_Trees is
function Iterate_Children
(Container : Tree;
Parent : Cursor)
- return Tree_Iterator_Interfaces.Reversible_Iterator'Class
+ return Tree_Iterator_Interfaces.Reversible_Iterator'Class
is
pragma Unreferenced (Container);
begin
@@ -2039,10 +2034,9 @@ package body Ada.Containers.Bounded_Multiway_Trees is
end Next;
function Next
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor
is
-
begin
if Object.Container /= Position.Container then
raise Program_Error;
@@ -2201,7 +2195,7 @@ package body Ada.Containers.Bounded_Multiway_Trees is
--------------
overriding function Previous
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor
is
begin
diff --git a/gcc/ada/a-cbmutr.ads b/gcc/ada/a-cbmutr.ads
index e014f82d453..797b6ea6214 100644
--- a/gcc/ada/a-cbmutr.ads
+++ b/gcc/ada/a-cbmutr.ads
@@ -182,7 +182,7 @@ package Ada.Containers.Bounded_Multiway_Trees is
function Iterate_Children
(Container : Tree;
Parent : Cursor)
- return Tree_Iterator_Interfaces.Reversible_Iterator'Class;
+ return Tree_Iterator_Interfaces.Reversible_Iterator'Class;
function Child_Count (Parent : Cursor) return Count_Type;
diff --git a/gcc/ada/a-cborse.adb b/gcc/ada/a-cborse.adb
index 1974c6cccef..674d2abee33 100644
--- a/gcc/ada/a-cborse.adb
+++ b/gcc/ada/a-cborse.adb
@@ -326,7 +326,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function New_Node return Count_Type is
Result : Count_Type;
-
begin
Allocate (Target, Result);
return Result;
@@ -376,13 +375,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Ceiling (Container : Set; Item : Element_Type) return Cursor is
Node : constant Count_Type :=
Element_Keys.Ceiling (Container, Item);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Ceiling;
-----------
@@ -425,10 +420,8 @@ package body Ada.Containers.Bounded_Ordered_Sets is
begin
if Capacity = 0 then
C := Source.Length;
-
elsif Capacity >= Source.Length then
C := Capacity;
-
else
raise Capacity_Error with "Capacity value too small";
end if;
@@ -479,7 +472,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
procedure Delete_First (Container : in out Set) is
X : constant Count_Type := Container.First;
-
begin
if X /= 0 then
Tree_Operations.Delete_Node_Sans_Free (Container, X);
@@ -493,7 +485,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
procedure Delete_Last (Container : in out Set) is
X : constant Count_Type := Container.Last;
-
begin
if X /= 0 then
Tree_Operations.Delete_Node_Sans_Free (Container, X);
@@ -533,13 +524,7 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
begin
- if Left < Right
- or else Right < Left
- then
- return False;
- else
- return True;
- end if;
+ return (if Left < Right or else Right < Left then False else True);
end Equivalent_Elements;
---------------------
@@ -559,13 +544,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Is_Equivalent_Node_Node (L, R : Node_Type) return Boolean is
begin
- if L.Element < R.Element then
- return False;
- elsif R.Element < L.Element then
- return False;
- else
- return True;
- end if;
+ return (if L.Element < R.Element then False
+ elsif R.Element < L.Element then False
+ else True);
end Is_Equivalent_Node_Node;
-- Start of processing for Equivalent_Sets
@@ -580,7 +561,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
procedure Exclude (Container : in out Set; Item : Element_Type) is
X : constant Count_Type := Element_Keys.Find (Container, Item);
-
begin
if X /= 0 then
Tree_Operations.Delete_Node_Sans_Free (Container, X);
@@ -594,13 +574,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Find (Container : Set; Item : Element_Type) return Cursor is
Node : constant Count_Type := Element_Keys.Find (Container, Item);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
-----------
@@ -609,23 +585,15 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function First (Container : Set) return Cursor is
begin
- if Container.First = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Container.First);
+ return (if Container.First = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Container.First));
end First;
function First (Object : Iterator) return Cursor is
begin
- if Object.Container.First = 0 then
- return No_Element;
- else
- return
- Cursor'(
- Object.Container.all'Unrestricted_Access,
- Object.Container.First);
- end if;
+ return (if Object.Container.First = 0 then No_Element
+ else Cursor'(Object.Container.all'Unrestricted_Access,
+ Object.Container.First));
end First;
-------------------
@@ -647,13 +615,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Floor (Container : Set; Item : Element_Type) return Cursor is
Node : constant Count_Type := Element_Keys.Floor (Container, Item);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Floor;
------------------
@@ -694,13 +658,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Ceiling (Container : Set; Key : Key_Type) return Cursor is
Node : constant Count_Type :=
Key_Keys.Ceiling (Container, Key);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Ceiling;
--------------
@@ -749,13 +709,7 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
begin
- if Left < Right
- or else Right < Left
- then
- return False;
- else
- return True;
- end if;
+ return (if Left < Right or else Right < Left then False else True);
end Equivalent_Keys;
-------------
@@ -764,7 +718,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
procedure Exclude (Container : in out Set; Key : Key_Type) is
X : constant Count_Type := Key_Keys.Find (Container, Key);
-
begin
if X /= 0 then
Tree_Operations.Delete_Node_Sans_Free (Container, X);
@@ -778,13 +731,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Find (Container : Set; Key : Key_Type) return Cursor is
Node : constant Count_Type := Key_Keys.Find (Container, Key);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
-----------
@@ -793,13 +742,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Floor (Container : Set; Key : Key_Type) return Cursor is
Node : constant Count_Type := Key_Keys.Floor (Container, Key);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Floor;
-------------------------
@@ -1069,7 +1014,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function New_Node return Count_Type is
Result : Count_Type;
-
begin
Allocate (Container, Result);
return Result;
@@ -1133,7 +1077,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function New_Node return Count_Type is
Result : Count_Type;
-
begin
Allocate (Dst_Set, Result);
return Result;
@@ -1287,22 +1230,15 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Last (Container : Set) return Cursor is
begin
- if Container.Last = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Container.Last);
+ return (if Container.Last = 0 then No_Element
+ else Cursor'(Container'Unrestricted_Access, Container.Last));
end Last;
function Last (Object : Iterator) return Cursor is
begin
- if Object.Container.Last = 0 then
- return No_Element;
- else
- return Cursor'(
- Object.Container.all'Unrestricted_Access,
- Object.Container.Last);
- end if;
+ return (if Object.Container.Last = 0 then No_Element
+ else Cursor'(Object.Container.all'Unrestricted_Access,
+ Object.Container.Last));
end Last;
------------------
@@ -1388,7 +1324,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function Next (Object : Iterator; Position : Cursor) return Cursor is
pragma Unreferenced (Object);
-
begin
return Next (Position);
end Next;
@@ -1427,13 +1362,9 @@ package body Ada.Containers.Bounded_Ordered_Sets is
Tree_Operations.Previous
(Position.Container.all,
Position.Node);
-
begin
- if Node = 0 then
- return No_Element;
- end if;
-
- return Cursor'(Position.Container, Node);
+ return (if Node = 0 then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Previous;
@@ -1466,7 +1397,6 @@ package body Ada.Containers.Bounded_Ordered_Sets is
declare
S : Set renames Position.Container.all;
-
B : Natural renames S.Busy;
L : Natural renames S.Lock;
@@ -1608,11 +1538,10 @@ package body Ada.Containers.Bounded_Ordered_Sets is
function New_Node return Count_Type is
begin
Node.Element := Item;
- Node.Color := Red_Black_Trees.Red;
- Node.Parent := 0;
- Node.Right := 0;
- Node.Left := 0;
-
+ Node.Color := Red_Black_Trees.Red;
+ Node.Parent := 0;
+ Node.Right := 0;
+ Node.Left := 0;
return Index;
end New_Node;
diff --git a/gcc/ada/a-cbprqu.adb b/gcc/ada/a-cbprqu.adb
index 09a06b277ad..cb96167be41 100644
--- a/gcc/ada/a-cbprqu.adb
+++ b/gcc/ada/a-cbprqu.adb
@@ -44,6 +44,24 @@ package body Ada.Containers.Bounded_Priority_Queues is
List.Container.Delete_First;
end Dequeue;
+ procedure Dequeue
+ (List : in out List_Type;
+ At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean)
+ is
+ begin
+ if List.Length = 0
+ or else not Before (At_Least, Get_Priority (List.First_Element))
+ then
+ Success := False;
+ return;
+ end if;
+
+ List.Dequeue (Element);
+ Success := True;
+ end Dequeue;
+
-------------
-- Enqueue --
-------------
@@ -62,8 +80,10 @@ package body Ada.Containers.Bounded_Priority_Queues is
begin
C := List.Container.First;
while Has_Element (C) loop
- -- ???
+
+ -- ??? why is following commented out ???
-- if Before (P, Get_Priority (List.Constant_Reference (C))) then
+
if Before (P, Get_Priority (Element (C))) then
List.Container.Insert (C, New_Item);
exit;
@@ -83,6 +103,20 @@ package body Ada.Containers.Bounded_Priority_Queues is
end if;
end Enqueue;
+ -------------------
+ -- First_Element --
+ -------------------
+
+ function First_Element
+ (List : List_Type) return Queue_Interfaces.Element_Type
+ is
+ begin
+
+ -- Use Constant_Reference for this. ???
+
+ return List.Container.First_Element;
+ end First_Element;
+
------------
-- Length --
------------
@@ -125,14 +159,18 @@ package body Ada.Containers.Bounded_Priority_Queues is
List.Dequeue (Element);
end Dequeue;
- -- ???
- -- entry Dequeue_Only_High_Priority
- -- (Low_Priority : Queue_Priority;
- -- Element : out Queue_Interfaces.Element_Type) when True
- -- is
- -- begin
- -- null;
- -- end Dequeue_Only_High_Priority;
+ --------------------------------
+ -- Dequeue_Only_High_Priority --
+ --------------------------------
+
+ procedure Dequeue_Only_High_Priority
+ (At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean)
+ is
+ begin
+ List.Dequeue (At_Least, Element, Success);
+ end Dequeue_Only_High_Priority;
--------------
-- Enqueue --
diff --git a/gcc/ada/a-cbprqu.ads b/gcc/ada/a-cbprqu.ads
index 589ee313894..aa184a1cc5a 100644
--- a/gcc/ada/a-cbprqu.ads
+++ b/gcc/ada/a-cbprqu.ads
@@ -54,11 +54,11 @@ generic
package Ada.Containers.Bounded_Priority_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type (Capacity : Count_Type) is tagged limited private;
@@ -70,6 +70,15 @@ package Ada.Containers.Bounded_Priority_Queues is
(List : in out List_Type;
Element : out Queue_Interfaces.Element_Type);
+ procedure Dequeue
+ (List : in out List_Type;
+ At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean);
+
+ function First_Element
+ (List : List_Type) return Queue_Interfaces.Element_Type;
+
function Length (List : List_Type) return Count_Type;
function Max_Length (List : List_Type) return Count_Type;
@@ -92,9 +101,7 @@ package Ada.Containers.Bounded_Priority_Queues is
protected type Queue
(Capacity : Count_Type := Default_Capacity;
Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
overriding
entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
@@ -102,11 +109,18 @@ package Ada.Containers.Bounded_Priority_Queues is
overriding
entry Dequeue (Element : out Queue_Interfaces.Element_Type);
- -- ???
- -- not overriding
- -- entry Dequeue_Only_High_Priority
- -- (Low_Priority : Queue_Priority;
- -- Element : out Queue_Interfaces.Element_Type);
+ -- The priority queue operation Dequeue_Only_High_Priority had been a
+ -- protected entry in early drafts of AI05-0159, but it was discovered
+ -- that that operation as specified was not in fact implementable. The
+ -- operation was changed from an entry to a protected procedure per the
+ -- ARG meeting in Edinburgh (June 2011), with a different signature and
+ -- semantics.
+
+ not overriding
+ procedure Dequeue_Only_High_Priority
+ (At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean);
overriding
function Current_Use return Count_Type;
@@ -115,6 +129,7 @@ package Ada.Containers.Bounded_Priority_Queues is
function Peak_Use return Count_Type;
private
+
List : Implementation.List_Type (Capacity);
end Queue;
diff --git a/gcc/ada/a-cbsyqu.ads b/gcc/ada/a-cbsyqu.ads
index 8d25359469d..0d6e3c39958 100644
--- a/gcc/ada/a-cbsyqu.ads
+++ b/gcc/ada/a-cbsyqu.ads
@@ -44,11 +44,11 @@ generic
package Ada.Containers.Bounded_Synchronized_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type (Capacity : Count_Type) is tagged limited private;
@@ -83,9 +83,7 @@ package Ada.Containers.Bounded_Synchronized_Queues is
protected type Queue
(Capacity : Count_Type := Default_Capacity;
Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
overriding
entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
diff --git a/gcc/ada/a-cihase.adb b/gcc/ada/a-cihase.adb
index dd43229b5e2..e52f38bba9f 100644
--- a/gcc/ada/a-cihase.adb
+++ b/gcc/ada/a-cihase.adb
@@ -49,7 +49,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
overriding function First (Object : Iterator) return Cursor;
overriding function Next
- (Object : Iterator;
+ (Object : Iterator;
Position : Cursor) return Cursor;
-----------------------
@@ -426,8 +426,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
-- Equivalent_Elements --
-------------------------
- function Equivalent_Elements (Left, Right : Cursor)
- return Boolean is
+ function Equivalent_Elements (Left, Right : Cursor) return Boolean is
begin
if Left.Node = null then
raise Constraint_Error with
@@ -457,8 +456,10 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Right.Node.Element.all);
end Equivalent_Elements;
- function Equivalent_Elements (Left : Cursor; Right : Element_Type)
- return Boolean is
+ function Equivalent_Elements
+ (Left : Cursor;
+ Right : Element_Type) return Boolean
+ is
begin
if Left.Node = null then
raise Constraint_Error with
@@ -475,8 +476,10 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
return Equivalent_Elements (Left.Node.Element.all, Right);
end Equivalent_Elements;
- function Equivalent_Elements (Left : Element_Type; Right : Cursor)
- return Boolean is
+ function Equivalent_Elements
+ (Left : Element_Type;
+ Right : Cursor) return Boolean
+ is
begin
if Right.Node = null then
raise Constraint_Error with
@@ -497,8 +500,10 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
-- Equivalent_Keys --
---------------------
- function Equivalent_Keys (Key : Element_Type; Node : Node_Access)
- return Boolean is
+ function Equivalent_Keys
+ (Key : Element_Type;
+ Node : Node_Access) return Boolean
+ is
begin
return Equivalent_Elements (Key, Node.Element.all);
end Equivalent_Keys;
@@ -535,13 +540,9 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Item : Element_Type) return Cursor
is
Node : constant Node_Access := Element_Keys.Find (Container.HT, Item);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
--------------------
@@ -604,23 +605,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function First (Container : Set) return Cursor is
Node : constant Node_Access := HT_Ops.First (Container.HT);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end First;
function First (Object : Iterator) return Cursor is
Node : constant Node_Access := HT_Ops.First (Object.Container.HT);
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Object.Container, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Object.Container, Node));
end First;
----------
@@ -750,7 +744,6 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function New_Node (Next : Node_Access) return Node_Access is
Element : Element_Access := new Element_Type'(New_Item);
-
begin
return new Node_Type'(Element, Next);
exception
@@ -1025,13 +1018,9 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
declare
HT : Hash_Table_Type renames Position.Container.HT;
Node : constant Node_Access := HT_Ops.Next (HT, Position.Node);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Position.Container, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Next;
@@ -1041,7 +1030,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
end Next;
function Next
- (Object : Iterator;
+ (Object : Iterator;
Position : Cursor) return Cursor
is
begin
@@ -1050,11 +1039,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
"Position cursor designates wrong set";
end if;
- if Position.Node = null then
- return No_Element;
- end if;
-
- return Next (Position);
+ return (if Position.Node = null then No_Element else Next (Position));
end Next;
-------------
@@ -1166,7 +1151,6 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
(Stream : not null access Root_Stream_Type'Class) return Node_Access
is
X : Element_Access := new Element_Type'(Element_Type'Input (Stream));
-
begin
return new Node_Type'(X, null);
exception
@@ -1183,10 +1167,9 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
(Container : aliased Set;
Position : Cursor) return Constant_Reference_Type
is
- begin
pragma Unreferenced (Container);
-
- return (Element => Position.Node.Element);
+ begin
+ return (Element => Position.Node.Element.all'Access);
end Constant_Reference;
-------------
@@ -1301,8 +1284,7 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Iterate_Source_When_Empty_Target : declare
procedure Process (Src_Node : Node_Access);
- procedure Iterate is
- new HT_Ops.Generic_Iteration (Process);
+ procedure Iterate is new HT_Ops.Generic_Iteration (Process);
-------------
-- Process --
@@ -1535,12 +1517,10 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
------------
function To_Set (New_Item : Element_Type) return Set is
- HT : Hash_Table_Type;
-
+ HT : Hash_Table_Type;
Node : Node_Access;
Inserted : Boolean;
pragma Unreferenced (Node, Inserted);
-
begin
Insert (HT, New_Item, Node, Inserted);
return Set'(Controlled with HT);
@@ -1578,7 +1558,6 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
function New_Node (Next : Node_Access) return Node_Access is
Tgt : Element_Access := new Element_Type'(Src);
-
begin
return new Node_Type'(Tgt, Next);
exception
@@ -1655,14 +1634,10 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
-------------
procedure Process (L_Node : Node_Access) is
- Src : Element_Type renames L_Node.Element.all;
-
- J : constant Hash_Type := Hash (Src) mod Buckets'Length;
-
+ Src : Element_Type renames L_Node.Element.all;
+ J : constant Hash_Type := Hash (Src) mod Buckets'Length;
Bucket : Node_Access renames Buckets (J);
-
- Tgt : Element_Access := new Element_Type'(Src);
-
+ Tgt : Element_Access := new Element_Type'(Src);
begin
Bucket := new Node_Type'(Tgt, Bucket);
exception
@@ -1940,13 +1915,9 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
Key : Key_Type) return Cursor
is
Node : constant Node_Access := Key_Keys.Find (Container.HT, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
---------
@@ -2101,16 +2072,16 @@ package body Ada.Containers.Indefinite_Hashed_Sets is
is
pragma Unreferenced (Container);
begin
- return (Element => Position.Node.Element);
+ return (Element => Position.Node.Element.all'Access);
end Reference_Preserving_Key;
function Reference_Preserving_Key
(Container : aliased in out Set;
- Key : Key_Type) return Reference_Type
+ Key : Key_Type) return Reference_Type
is
Position : constant Cursor := Find (Container, Key);
begin
- return (Element => Position.Node.Element);
+ return (Element => Position.Node.Element.all'Access);
end Reference_Preserving_Key;
end Generic_Keys;
diff --git a/gcc/ada/a-cihase.ads b/gcc/ada/a-cihase.ads
index b055c1be153..860034469ea 100644
--- a/gcc/ada/a-cihase.ads
+++ b/gcc/ada/a-cihase.ads
@@ -414,13 +414,11 @@ package Ada.Containers.Indefinite_Hashed_Sets is
function Reference_Preserving_Key
(Container : aliased in out Set;
- Position : Cursor)
- return Reference_Type;
+ Position : Cursor) return Reference_Type;
function Reference_Preserving_Key
(Container : aliased in out Set;
- Key : Key_Type)
- return Reference_Type;
+ Key : Key_Type) return Reference_Type;
private
type Reference_Type (Element : not null access Element_Type)
@@ -428,7 +426,6 @@ package Ada.Containers.Indefinite_Hashed_Sets is
end Generic_Keys;
private
-
pragma Inline (Next);
type Node_Type;
diff --git a/gcc/ada/a-ciorma.adb b/gcc/ada/a-ciorma.adb
index c30abd08046..3de57c76aa4 100644
--- a/gcc/ada/a-ciorma.adb
+++ b/gcc/ada/a-ciorma.adb
@@ -36,6 +36,7 @@ with Ada.Containers.Red_Black_Trees.Generic_Keys;
pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
package body Ada.Containers.Indefinite_Ordered_Maps is
+ pragma Suppress (All_Checks);
type Iterator is new
Map_Iterator_Interfaces.Reversible_Iterator with record
@@ -279,8 +280,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
-- Adjust --
------------
- procedure Adjust is
- new Tree_Operations.Generic_Adjust (Copy_Tree);
+ procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
procedure Adjust (Container : in out Map) is
begin
@@ -293,21 +293,16 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function Ceiling (Container : Map; Key : Key_Type) return Cursor is
Node : constant Node_Access := Key_Ops.Ceiling (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Ceiling;
-----------
-- Clear --
-----------
- procedure Clear is
- new Tree_Operations.Generic_Clear (Delete_Tree);
+ procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
procedure Clear (Container : in out Map) is
begin
@@ -331,7 +326,9 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
(Container : Map;
Key : Key_Type) return Constant_Reference_Type
is
- begin return (Element => Container.Element (Key)'Unrestricted_Access);
+ Node : aliased Element_Type := Element (Container, Key);
+ begin
+ return (Element => Node'Access);
end Constant_Reference;
--------------
@@ -350,6 +347,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function Copy_Node (Source : Node_Access) return Node_Access is
K : Key_Access := new Key_Type'(Source.Key.all);
E : Element_Access;
+
begin
E := new Element_Type'(Source.Element.all);
@@ -418,7 +416,6 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
procedure Delete_First (Container : in out Map) is
X : Node_Access := Container.Tree.First;
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
@@ -432,7 +429,6 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
procedure Delete_Last (Container : in out Map) is
X : Node_Access := Container.Tree.Last;
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
@@ -479,13 +475,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
begin
- if Left < Right
- or else Right < Left
- then
- return False;
- else
- return True;
- end if;
+ return (if Left < Right or else Right < Left then False else True);
end Equivalent_Keys;
-------------
@@ -494,7 +484,6 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
procedure Exclude (Container : in out Map; Key : Key_Type) is
X : Node_Access := Key_Ops.Find (Container.Tree, Key);
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
@@ -508,13 +497,9 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function Find (Container : Map; Key : Key_Type) return Cursor is
Node : constant Node_Access := Key_Ops.Find (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
-----------
@@ -523,25 +508,17 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function First (Container : Map) return Cursor is
T : Tree_Type renames Container.Tree;
-
begin
- if T.First = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, T.First);
+ return (if T.First = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, T.First));
end First;
function First (Object : Iterator) return Cursor is
M : constant Map_Access := Object.Container;
N : constant Node_Access := M.Tree.First;
-
begin
- if N = null then
- return No_Element;
- else
- return Cursor'(Object.Container.all'Unchecked_Access, N);
- end if;
+ return (if N = null then No_Element
+ else Cursor'(Object.Container.all'Unchecked_Access, N));
end First;
-------------------
@@ -580,13 +557,9 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function Floor (Container : Map; Key : Key_Type) return Cursor is
Node : constant Node_Access := Key_Ops.Floor (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Floor;
----------
@@ -608,6 +581,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
begin
Free_Key (X.Key);
+
exception
when others =>
X.Key := null;
@@ -625,6 +599,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
begin
Free_Element (X.Element);
+
exception
when others =>
X.Element := null;
@@ -771,18 +746,11 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
-- Is_Equal_Node_Node --
------------------------
- function Is_Equal_Node_Node
- (L, R : Node_Access) return Boolean is
+ function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
begin
- if L.Key.all < R.Key.all then
- return False;
-
- elsif R.Key.all < L.Key.all then
- return False;
-
- else
- return L.Element.all = R.Element.all;
- end if;
+ return (if L.Key.all < R.Key.all then False
+ elsif R.Key.all < L.Key.all then False
+ else L.Element.all = R.Element.all);
end Is_Equal_Node_Node;
-------------------------
@@ -856,12 +824,13 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
is
Node : constant Node_Access := Container.Tree.First;
It : constant Iterator := (Container'Unrestricted_Access, Node);
-
begin
return It;
end Iterate;
- function Iterate (Container : Map; Start : Cursor)
+ function Iterate
+ (Container : Map;
+ Start : Cursor)
return Map_Iterator_Interfaces.Reversible_Iterator'class
is
It : constant Iterator := (Container'Unrestricted_Access, Start.Node);
@@ -897,24 +866,17 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
function Last (Container : Map) return Cursor is
T : Tree_Type renames Container.Tree;
-
begin
- if T.Last = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, T.Last);
+ return (if T.Last = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, T.Last));
end Last;
function Last (Object : Iterator) return Cursor is
M : constant Map_Access := Object.Container;
N : constant Node_Access := M.Tree.Last;
begin
- if N = null then
- return No_Element;
- else
- return Cursor'(Object.Container.all'Unchecked_Access, N);
- end if;
+ return (if N = null then No_Element
+ else Cursor'(Object.Container.all'Unchecked_Access, N));
end Last;
------------------
@@ -969,8 +931,7 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
-- Move --
----------
- procedure Move is
- new Tree_Operations.Generic_Move (Clear);
+ procedure Move is new Tree_Operations.Generic_Move (Clear);
procedure Move (Target : in out Map; Source : in out Map) is
begin
@@ -996,13 +957,9 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
declare
Node : constant Node_Access :=
Tree_Operations.Next (Position.Node);
-
begin
- if Node = null then
- return No_Element;
- else
- return Cursor'(Position.Container, Node);
- end if;
+ return (if Node = null then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Next;
@@ -1016,11 +973,8 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
Position : Cursor) return Cursor
is
begin
- if Position.Node = null then
- return No_Element;
- else
- return (Object.Container, Tree_Operations.Next (Position.Node));
- end if;
+ return (if Position.Node = null then No_Element
+ else (Object.Container, Tree_Operations.Next (Position.Node)));
end Next;
------------
@@ -1051,13 +1005,9 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
declare
Node : constant Node_Access :=
Tree_Operations.Previous (Position.Node);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Position.Container, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Previous;
@@ -1071,11 +1021,9 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
Position : Cursor) return Cursor
is
begin
- if Position.Node = null then
- return No_Element;
- else
- return (Object.Container, Tree_Operations.Previous (Position.Node));
- end if;
+ return
+ (if Position.Node = null then No_Element
+ else (Object.Container, Tree_Operations.Previous (Position.Node)));
end Previous;
-------------------
@@ -1203,8 +1151,9 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
Key : Key_Type)
return Reference_Type
is
+ Node : aliased Element_Type := Element (Container, Key);
begin
- return (Element => Container.Element (Key)'Unrestricted_Access);
+ return (Element => Node'Access);
end Reference;
-------------
diff --git a/gcc/ada/a-ciorse.adb b/gcc/ada/a-ciorse.adb
index a330ed8b6c5..4257f0974e6 100644
--- a/gcc/ada/a-ciorse.adb
+++ b/gcc/ada/a-ciorse.adb
@@ -314,8 +314,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
-- Adjust --
------------
- procedure Adjust is
- new Tree_Operations.Generic_Adjust (Copy_Tree);
+ procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
procedure Adjust (Container : in out Set) is
begin
@@ -329,13 +328,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Ceiling (Container : Set; Item : Element_Type) return Cursor is
Node : constant Node_Access :=
Element_Keys.Ceiling (Container.Tree, Item);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Ceiling;
-----------
@@ -433,7 +428,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
procedure Delete_First (Container : in out Set) is
Tree : Tree_Type renames Container.Tree;
X : Node_Access := Tree.First;
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Tree, X);
@@ -448,7 +442,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
procedure Delete_Last (Container : in out Set) is
Tree : Tree_Type renames Container.Tree;
X : Node_Access := Tree.Last;
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Tree, X);
@@ -466,8 +459,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
end Difference;
function Difference (Left, Right : Set) return Set is
- Tree : constant Tree_Type :=
- Set_Ops.Difference (Left.Tree, Right.Tree);
+ Tree : constant Tree_Type := Set_Ops.Difference (Left.Tree, Right.Tree);
begin
return Set'(Controlled with Tree);
end Difference;
@@ -498,9 +490,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
begin
- if Left < Right
- or else Right < Left
- then
+ if Left < Right or else Right < Left then
return False;
else
return True;
@@ -547,7 +537,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
procedure Exclude (Container : in out Set; Item : Element_Type) is
X : Node_Access :=
Element_Keys.Find (Container.Tree, Item);
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
@@ -577,11 +566,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function First (Container : Set) return Cursor is
begin
- if Container.Tree.First = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
+ return
+ (if Container.Tree.First = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
end First;
function First (Object : Iterator) return Cursor is
@@ -611,11 +598,8 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
Node : constant Node_Access :=
Element_Keys.Floor (Container.Tree, Item);
begin
- if Node = null then
- return No_Element;
- else
- return Cursor'(Container'Unrestricted_Access, Node);
- end if;
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Floor;
----------
@@ -685,13 +669,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Ceiling (Container : Set; Key : Key_Type) return Cursor is
Node : constant Node_Access :=
Key_Keys.Ceiling (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Ceiling;
--------------
@@ -741,9 +721,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
begin
- if Left < Right
- or else Right < Left
- then
+ if Left < Right or else Right < Left then
return False;
else
return True;
@@ -756,7 +734,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
procedure Exclude (Container : in out Set; Key : Key_Type) is
X : Node_Access := Key_Keys.Find (Container.Tree, Key);
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
@@ -771,13 +748,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Find (Container : Set; Key : Key_Type) return Cursor is
Node : constant Node_Access :=
Key_Keys.Find (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
-----------
@@ -787,13 +760,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Floor (Container : Set; Key : Key_Type) return Cursor is
Node : constant Node_Access :=
Key_Keys.Floor (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Floor;
-------------------------
@@ -802,7 +771,8 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Is_Greater_Key_Node
(Left : Key_Type;
- Right : Node_Access) return Boolean is
+ Right : Node_Access) return Boolean
+ is
begin
return Key (Right.Element.all) < Left;
end Is_Greater_Key_Node;
@@ -813,7 +783,8 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Is_Less_Key_Node
(Left : Key_Type;
- Right : Node_Access) return Boolean is
+ Right : Node_Access) return Boolean
+ is
begin
return Left < Key (Right.Element.all);
end Is_Less_Key_Node;
@@ -1179,7 +1150,8 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Is_Greater_Element_Node
(Left : Element_Type;
- Right : Node_Access) return Boolean is
+ Right : Node_Access) return Boolean
+ is
begin
-- e > node same as node < e
@@ -1192,7 +1164,8 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Is_Less_Element_Node
(Left : Element_Type;
- Right : Node_Access) return Boolean is
+ Right : Node_Access) return Boolean
+ is
begin
return Left < Right.Element.all;
end Is_Less_Element_Node;
@@ -1283,22 +1256,16 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
function Last (Container : Set) return Cursor is
begin
- if Container.Tree.Last = null then
- return No_Element;
- else
- return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
- end if;
+ return
+ (if Container.Tree.Last = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
end Last;
function Last (Object : Iterator) return Cursor is
begin
- if Object.Container.Tree.Last = null then
- return No_Element;
- else
- return Cursor'(
- Object.Container.all'Unrestricted_Access,
- Object.Container.Tree.Last);
- end if;
+ return (if Object.Container.Tree.Last = null then No_Element
+ else Cursor'(Object.Container.all'Unrestricted_Access,
+ Object.Container.Tree.Last));
end Last;
------------------
@@ -1336,8 +1303,7 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
-- Move --
----------
- procedure Move is
- new Tree_Operations.Generic_Move (Clear);
+ procedure Move is new Tree_Operations.Generic_Move (Clear);
procedure Move (Target : in out Set; Source : in out Set) is
begin
@@ -1369,13 +1335,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
declare
Node : constant Node_Access :=
Tree_Operations.Next (Position.Node);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Position.Container, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Next;
@@ -1431,13 +1393,9 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
declare
Node : constant Node_Access :=
Tree_Operations.Previous (Position.Node);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Position.Container, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Previous;
@@ -1608,15 +1566,15 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
pragma Inline (New_Node);
procedure Local_Insert_Post is
- new Element_Keys.Generic_Insert_Post (New_Node);
+ new Element_Keys.Generic_Insert_Post (New_Node);
procedure Local_Insert_Sans_Hint is
- new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
+ new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
procedure Local_Insert_With_Hint is
- new Element_Keys.Generic_Conditional_Insert_With_Hint
- (Local_Insert_Post,
- Local_Insert_Sans_Hint);
+ new Element_Keys.Generic_Conditional_Insert_With_Hint
+ (Local_Insert_Post,
+ Local_Insert_Sans_Hint);
--------------
-- New_Node --
@@ -1629,7 +1587,6 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
Node.Parent := null;
Node.Right := null;
Node.Left := null;
-
return Node;
end New_Node;
@@ -1829,12 +1786,10 @@ package body Ada.Containers.Indefinite_Ordered_Sets is
------------
function To_Set (New_Item : Element_Type) return Set is
- Tree : Tree_Type;
-
+ Tree : Tree_Type;
Node : Node_Access;
Inserted : Boolean;
pragma Unreferenced (Node, Inserted);
-
begin
Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
return Set'(Controlled with Tree);
diff --git a/gcc/ada/a-comutr.adb b/gcc/ada/a-comutr.adb
index 0fcb3d6d51c..86be79ffc35 100644
--- a/gcc/ada/a-comutr.adb
+++ b/gcc/ada/a-comutr.adb
@@ -48,16 +48,16 @@ package body Ada.Containers.Multiway_Trees is
overriding function First (Object : Iterator) return Cursor;
overriding function Next
- (Object : Iterator;
+ (Object : Iterator;
Position : Cursor) return Cursor;
overriding function First (Object : Child_Iterator) return Cursor;
overriding function Next
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor;
overriding function Previous
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor;
overriding function Last (Object : Child_Iterator) return Cursor;
@@ -327,11 +327,8 @@ package body Ada.Containers.Multiway_Trees is
function Child_Count (Parent : Cursor) return Count_Type is
begin
- if Parent = No_Element then
- return 0;
- else
- return Child_Count (Parent.Node.Children);
- end if;
+ return (if Parent = No_Element
+ then 0 else Child_Count (Parent.Node.Children));
end Child_Count;
function Child_Count (Children : Children_Type) return Count_Type is
@@ -1010,12 +1007,10 @@ package body Ada.Containers.Multiway_Trees is
-- raise Program_Error with "Position cursor not in container";
-- end if;
- if Is_Root (Position) then
- Result := Find_In_Children (Position.Node, Item);
-
- else
- Result := Find_In_Subtree (Position.Node, Item);
- end if;
+ Result :=
+ (if Is_Root (Position)
+ then Find_In_Children (Position.Node, Item)
+ else Find_In_Subtree (Position.Node, Item));
if Result = null then
return No_Element;
@@ -1437,7 +1432,7 @@ package body Ada.Containers.Multiway_Trees is
function Iterate_Children
(Container : Tree;
Parent : Cursor)
- return Tree_Iterator_Interfaces.Reversible_Iterator'Class
+ return Tree_Iterator_Interfaces.Reversible_Iterator'Class
is
pragma Unreferenced (Container);
begin
@@ -1457,8 +1452,8 @@ package body Ada.Containers.Multiway_Trees is
end Iterate_Subtree;
procedure Iterate_Subtree
- (Position : Cursor;
- Process : not null access procedure (Position : Cursor))
+ (Position : Cursor;
+ Process : not null access procedure (Position : Cursor))
is
begin
if Position = No_Element then
@@ -1515,6 +1510,7 @@ package body Ada.Containers.Multiway_Trees is
function Last_Child (Parent : Cursor) return Cursor is
Node : Tree_Node_Access;
+
begin
if Parent = No_Element then
raise Constraint_Error with "Parent cursor has no element";
@@ -1575,7 +1571,7 @@ package body Ada.Containers.Multiway_Trees is
----------
function Next
- (Object : Iterator;
+ (Object : Iterator;
Position : Cursor) return Cursor
is
T : Tree renames Position.Container.all;
@@ -1635,18 +1631,12 @@ package body Ada.Containers.Multiway_Trees is
end Next;
function Next
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor
is
C : constant Tree_Node_Access := Position.Node.Next;
-
begin
- if C = null then
- return No_Element;
-
- else
- return (Object.Container, C);
- end if;
+ return (if C = null then No_Element else (Object.Container, C));
end Next;
------------------
@@ -1773,18 +1763,12 @@ package body Ada.Containers.Multiway_Trees is
--------------
overriding function Previous
- (Object : Child_Iterator;
+ (Object : Child_Iterator;
Position : Cursor) return Cursor
is
C : constant Tree_Node_Access := Position.Node.Prev;
-
begin
- if C = null then
- return No_Element;
-
- else
- return (Object.Container, C);
- end if;
+ return (if C = null then No_Element else (Object.Container, C));
end Previous;
----------------------
@@ -1793,15 +1777,10 @@ package body Ada.Containers.Multiway_Trees is
function Previous_Sibling (Position : Cursor) return Cursor is
begin
- if Position = No_Element then
- return No_Element;
- end if;
-
- if Position.Node.Prev = null then
- return No_Element;
- end if;
-
- return Cursor'(Position.Container, Position.Node.Prev);
+ return
+ (if Position = No_Element then No_Element
+ elsif Position.Node.Prev = null then No_Element
+ else Cursor'(Position.Container, Position.Node.Prev));
end Previous_Sibling;
procedure Previous_Sibling (Position : in out Cursor) is
diff --git a/gcc/ada/a-convec.adb b/gcc/ada/a-convec.adb
index a357cec8e89..a57f7fbd9a8 100644
--- a/gcc/ada/a-convec.adb
+++ b/gcc/ada/a-convec.adb
@@ -802,7 +802,7 @@ package body Ada.Containers.Vectors is
if Is_Empty (Object.Container.all) then
return No_Element;
else
- return Cursor'(Object.Container, Index_Type'First);
+ return (Object.Container, Index_Type'First);
end if;
end First;
@@ -1517,7 +1517,7 @@ package body Ada.Containers.Vectors is
Insert (Container, Index, New_Item);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := (Container'Unchecked_Access, Index);
end Insert;
procedure Insert
@@ -1600,7 +1600,7 @@ package body Ada.Containers.Vectors is
Insert (Container, Index, New_Item, Count);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := (Container'Unchecked_Access, Index);
end Insert;
procedure Insert
@@ -2017,7 +2017,7 @@ package body Ada.Containers.Vectors is
Insert_Space (Container, Index, Count => Count);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := (Container'Unchecked_Access, Index);
end Insert_Space;
--------------
@@ -2093,7 +2093,7 @@ package body Ada.Containers.Vectors is
if Is_Empty (Object.Container.all) then
return No_Element;
else
- return Cursor'(Object.Container, Object.Container.Last);
+ return (Object.Container, Object.Container.Last);
end if;
end Last;
@@ -2204,24 +2204,18 @@ package body Ada.Containers.Vectors is
function Next (Object : Iterator; Position : Cursor) return Cursor is
begin
- if Position.Index = Object.Container.Last then
- return No_Element;
- else
+ if Position.Index < Object.Container.Last then
return (Object.Container, Position.Index + 1);
+ else
+ return No_Element;
end if;
end Next;
- ----------
- -- Next --
- ----------
-
procedure Next (Position : in out Cursor) is
begin
if Position.Container = null then
return;
- end if;
-
- if Position.Index < Position.Container.Last then
+ elsif Position.Index < Position.Container.Last then
Position.Index := Position.Index + 1;
else
Position := No_Element;
@@ -2253,30 +2247,15 @@ package body Ada.Containers.Vectors is
-- Previous --
--------------
- procedure Previous (Position : in out Cursor) is
- begin
- if Position.Container = null then
- return;
- end if;
-
- if Position.Index > Index_Type'First then
- Position.Index := Position.Index - 1;
- else
- Position := No_Element;
- end if;
- end Previous;
-
function Previous (Position : Cursor) return Cursor is
begin
if Position.Container = null then
return No_Element;
- end if;
-
- if Position.Index > Index_Type'First then
+ elsif Position.Index > Index_Type'First then
return (Position.Container, Position.Index - 1);
+ else
+ return No_Element;
end if;
-
- return No_Element;
end Previous;
function Previous (Object : Iterator; Position : Cursor) return Cursor is
@@ -2288,6 +2267,17 @@ package body Ada.Containers.Vectors is
end if;
end Previous;
+ procedure Previous (Position : in out Cursor) is
+ begin
+ if Position.Container = null then
+ return;
+ elsif Position.Index > Index_Type'First then
+ Position.Index := Position.Index - 1;
+ else
+ Position := No_Element;
+ end if;
+ end Previous;
+
-------------------
-- Query_Element --
-------------------
@@ -2416,7 +2406,7 @@ package body Ada.Containers.Vectors is
return Constant_Reference_Type
is
begin
- if (Position) > Container.Last then
+ if Position > Container.Last then
raise Constraint_Error with "Index is out of range";
else
return (Element => Container.Elements.EA (Position)'Access);
@@ -3019,7 +3009,7 @@ package body Ada.Containers.Vectors is
if Index not in Index_Type'First .. Container.Last then
return No_Element;
else
- return Cursor'(Container'Unchecked_Access, Index);
+ return (Container'Unchecked_Access, Index);
end if;
end To_Cursor;
diff --git a/gcc/ada/a-convec.ads b/gcc/ada/a-convec.ads
index c6815d31ebb..c90cf01bde9 100644
--- a/gcc/ada/a-convec.ads
+++ b/gcc/ada/a-convec.ads
@@ -409,8 +409,8 @@ private
for Vector_Access'Storage_Size use 0;
type Cursor is record
- Container : Vector_Access;
- Index : Index_Type := Index_Type'First;
+ Container : Vector_Access;
+ Index : Index_Type := Index_Type'First;
end record;
procedure Write
diff --git a/gcc/ada/a-coorse.adb b/gcc/ada/a-coorse.adb
index d52ed67c9a0..915eed62117 100644
--- a/gcc/ada/a-coorse.adb
+++ b/gcc/ada/a-coorse.adb
@@ -288,13 +288,9 @@ package body Ada.Containers.Ordered_Sets is
function Ceiling (Container : Set; Item : Element_Type) return Cursor is
Node : constant Node_Access :=
Element_Keys.Ceiling (Container.Tree, Item);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Ceiling;
-----------
@@ -385,7 +381,6 @@ package body Ada.Containers.Ordered_Sets is
procedure Delete_First (Container : in out Set) is
Tree : Tree_Type renames Container.Tree;
X : Node_Access := Tree.First;
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Tree, X);
@@ -400,7 +395,6 @@ package body Ada.Containers.Ordered_Sets is
procedure Delete_Last (Container : in out Set) is
Tree : Tree_Type renames Container.Tree;
X : Node_Access := Tree.Last;
-
begin
if X /= null then
Tree_Operations.Delete_Node_Sans_Free (Tree, X);
@@ -446,13 +440,7 @@ package body Ada.Containers.Ordered_Sets is
function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
begin
- if Left < Right
- or else Right < Left
- then
- return False;
- else
- return True;
- end if;
+ return (if Left < Right or else Right < Left then False else True);
end Equivalent_Elements;
---------------------
@@ -472,13 +460,9 @@ package body Ada.Containers.Ordered_Sets is
function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
begin
- if L.Element < R.Element then
- return False;
- elsif R.Element < L.Element then
- return False;
- else
- return True;
- end if;
+ return (if L.Element < R.Element then False
+ elsif R.Element < L.Element then False
+ else True);
end Is_Equivalent_Node_Node;
-- Start of processing for Equivalent_Sets
@@ -508,13 +492,9 @@ package body Ada.Containers.Ordered_Sets is
function Find (Container : Set; Item : Element_Type) return Cursor is
Node : constant Node_Access :=
Element_Keys.Find (Container.Tree, Item);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
-----------
@@ -523,23 +503,16 @@ package body Ada.Containers.Ordered_Sets is
function First (Container : Set) return Cursor is
begin
- if Container.Tree.First = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
+ return
+ (if Container.Tree.First = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
end First;
function First (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
- else
- return
- Cursor'(
- Object.Container.all'Unrestricted_Access,
- Object.Container.Tree.First);
- end if;
+ return (if Object.Container = null then No_Element
+ else Cursor'(Object.Container.all'Unrestricted_Access,
+ Object.Container.Tree.First));
end First;
-------------------
@@ -562,13 +535,9 @@ package body Ada.Containers.Ordered_Sets is
function Floor (Container : Set; Item : Element_Type) return Cursor is
Node : constant Node_Access :=
Element_Keys.Floor (Container.Tree, Item);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Floor;
----------
@@ -578,13 +547,11 @@ package body Ada.Containers.Ordered_Sets is
procedure Free (X : in out Node_Access) is
procedure Deallocate is
new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
-
begin
if X /= null then
X.Parent := X;
- X.Left := X;
- X.Right := X;
-
+ X.Left := X;
+ X.Right := X;
Deallocate (X);
end if;
end Free;
@@ -627,13 +594,9 @@ package body Ada.Containers.Ordered_Sets is
function Ceiling (Container : Set; Key : Key_Type) return Cursor is
Node : constant Node_Access :=
Key_Keys.Ceiling (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Ceiling;
--------------
@@ -683,13 +646,7 @@ package body Ada.Containers.Ordered_Sets is
function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
begin
- if Left < Right
- or else Right < Left
- then
- return False;
- else
- return True;
- end if;
+ return (if Left < Right or else Right < Left then False else True);
end Equivalent_Keys;
-------------
@@ -698,7 +655,6 @@ package body Ada.Containers.Ordered_Sets is
procedure Exclude (Container : in out Set; Key : Key_Type) is
X : Node_Access := Key_Keys.Find (Container.Tree, Key);
-
begin
if X /= null then
Delete_Node_Sans_Free (Container.Tree, X);
@@ -712,13 +668,9 @@ package body Ada.Containers.Ordered_Sets is
function Find (Container : Set; Key : Key_Type) return Cursor is
Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Find;
-----------
@@ -727,13 +679,9 @@ package body Ada.Containers.Ordered_Sets is
function Floor (Container : Set; Key : Key_Type) return Cursor is
Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Container'Unrestricted_Access, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Node));
end Floor;
-------------------------
@@ -1214,22 +1162,16 @@ package body Ada.Containers.Ordered_Sets is
function Last (Container : Set) return Cursor is
begin
- if Container.Tree.Last = null then
- return No_Element;
- else
- return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
- end if;
+ return
+ (if Container.Tree.Last = null then No_Element
+ else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
end Last;
function Last (Object : Iterator) return Cursor is
begin
- if Object.Container = null then
- return No_Element;
- else
- return Cursor'(
- Object.Container.all'Unrestricted_Access,
- Object.Container.Tree.Last);
- end if;
+ return (if Object.Container = null then No_Element
+ else Cursor'(Object.Container.all'Unrestricted_Access,
+ Object.Container.Tree.Last));
end Last;
------------------
@@ -1267,8 +1209,7 @@ package body Ada.Containers.Ordered_Sets is
-- Move --
----------
- procedure Move is
- new Tree_Operations.Generic_Move (Clear);
+ procedure Move is new Tree_Operations.Generic_Move (Clear);
procedure Move (Target : in out Set; Source : in out Set) is
begin
@@ -1291,13 +1232,9 @@ package body Ada.Containers.Ordered_Sets is
declare
Node : constant Node_Access :=
Tree_Operations.Next (Position.Node);
-
begin
- if Node = null then
- return No_Element;
- end if;
-
- return Cursor'(Position.Container, Node);
+ return (if Node = null then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Next;
@@ -1347,11 +1284,8 @@ package body Ada.Containers.Ordered_Sets is
Node : constant Node_Access :=
Tree_Operations.Previous (Position.Node);
begin
- if Node = null then
- return No_Element;
- else
- return Cursor'(Position.Container, Node);
- end if;
+ return (if Node = null then No_Element
+ else Cursor'(Position.Container, Node));
end;
end Previous;
@@ -1429,11 +1363,9 @@ package body Ada.Containers.Ordered_Sets is
(Stream : not null access Root_Stream_Type'Class) return Node_Access
is
Node : Node_Access := new Node_Type;
-
begin
Element_Type'Read (Stream, Node.Element);
return Node;
-
exception
when others =>
Free (Node);
@@ -1532,11 +1464,10 @@ package body Ada.Containers.Ordered_Sets is
function New_Node return Node_Access is
begin
Node.Element := Item;
- Node.Color := Red;
- Node.Parent := null;
- Node.Right := null;
- Node.Left := null;
-
+ Node.Color := Red;
+ Node.Parent := null;
+ Node.Right := null;
+ Node.Left := null;
return Node;
end New_Node;
@@ -1547,9 +1478,7 @@ package body Ada.Containers.Ordered_Sets is
-- Start of processing for Replace_Element
begin
- if Item < Node.Element
- or else Node.Element < Item
- then
+ if Item < Node.Element or else Node.Element < Item then
null;
else
diff --git a/gcc/ada/a-csquin.ads b/gcc/ada/a-csquin.ads
index 2a4d0b36eec..7567444177e 100644
--- a/gcc/ada/a-csquin.ads
+++ b/gcc/ada/a-csquin.ads
@@ -42,12 +42,24 @@ package Ada.Containers.Synchronized_Queue_Interfaces is
procedure Enqueue
(Container : in out Queue;
New_Item : Element_Type) is abstract;
- -- with Is_Synchronized => By_Entry; ???
+
+ -- ???
+ -- This is the official Ada 2012 syntax:
+ -- with Synchronization => By_Entry;
+
+ -- This is the temporary work-around:
+ pragma Implemented (Enqueue, By_Entry);
procedure Dequeue
(Container : in out Queue;
Element : out Element_Type) is abstract;
- -- with Is_Synchronized => By_Entry; ???
+
+ -- ???
+ -- This is the official Ada 2012 syntax:
+ -- with Synchronization => By_Entry;
+
+ -- This is the temporary work-around:
+ pragma Implemented (Dequeue, By_Entry);
function Current_Use (Container : Queue) return Count_Type is abstract;
diff --git a/gcc/ada/a-cuprqu.adb b/gcc/ada/a-cuprqu.adb
index 2d11a2621b3..385aa5ce7d2 100644
--- a/gcc/ada/a-cuprqu.adb
+++ b/gcc/ada/a-cuprqu.adb
@@ -65,6 +65,24 @@ package body Ada.Containers.Unbounded_Priority_Queues is
Free (X);
end Dequeue;
+ procedure Dequeue
+ (List : in out List_Type;
+ At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean)
+ is
+ begin
+ if List.Length = 0
+ or else not Before (At_Least, Get_Priority (List.First.Element))
+ then
+ Success := False;
+ return;
+ end if;
+
+ List.Dequeue (Element);
+ Success := True;
+ end Dequeue;
+
-------------
-- Enqueue --
-------------
@@ -132,22 +150,6 @@ package body Ada.Containers.Unbounded_Priority_Queues is
end loop;
end Finalize;
- ------------------------
- -- Have_High_Priority --
- ------------------------
-
- -- ???
- -- function Have_High_Priority
- -- (List : List_Type;
- -- Low_Priority : Queue_Priority) return Boolean
- -- is
- -- begin
- -- if List.Length = 0 then
- -- return False;
- -- end if;
- -- return Before (Get_Priority (List.First.Element), Low_Priority);
- -- end Have_High_Priority;
-
------------
-- Length --
------------
@@ -190,14 +192,18 @@ package body Ada.Containers.Unbounded_Priority_Queues is
List.Dequeue (Element);
end Dequeue;
- -- ???
- -- entry Dequeue_Only_High_Priority
- -- (Low_Priority : Queue_Priority;
- -- Element : out Queue_Interfaces.Element_Type) when True
- -- is
- -- begin
- -- null;
- -- end Dequeue_Only_High_Priority;
+ --------------------------------
+ -- Dequeue_Only_High_Priority --
+ --------------------------------
+
+ procedure Dequeue_Only_High_Priority
+ (At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean)
+ is
+ begin
+ List.Dequeue (At_Least, Element, Success);
+ end Dequeue_Only_High_Priority;
-------------
-- Enqueue --
diff --git a/gcc/ada/a-cuprqu.ads b/gcc/ada/a-cuprqu.ads
index d31c8824458..3709f42aa29 100644
--- a/gcc/ada/a-cuprqu.ads
+++ b/gcc/ada/a-cuprqu.ads
@@ -52,11 +52,11 @@ generic
package Ada.Containers.Unbounded_Priority_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type is tagged limited private;
@@ -68,6 +68,12 @@ package Ada.Containers.Unbounded_Priority_Queues is
(List : in out List_Type;
Element : out Queue_Interfaces.Element_Type);
+ procedure Dequeue
+ (List : in out List_Type;
+ At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean);
+
function Length (List : List_Type) return Count_Type;
function Max_Length (List : List_Type) return Count_Type;
@@ -91,36 +97,35 @@ package Ada.Containers.Unbounded_Priority_Queues is
overriding
procedure Finalize (List : in out List_Type);
- -- ???
- -- not overriding
- -- function Have_High_Priority
- -- (List : List_Type;
- -- Low_Priority : Queue_Priority) return Boolean;
-
end Implementation;
protected type Queue (Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
- overriding
- entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
+ overriding
+ entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
- overriding
- entry Dequeue (Element : out Queue_Interfaces.Element_Type);
+ overriding
+ entry Dequeue (Element : out Queue_Interfaces.Element_Type);
- -- ???
- -- not overriding
- -- entry Dequeue_Only_High_Priority
- -- (Low_Priority : Queue_Priority;
- -- Element : out Queue_Interfaces.Element_Type);
+ -- The priority queue operation Dequeue_Only_High_Priority had been a
+ -- protected entry in early drafts of AI05-0159, but it was discovered
+ -- that that operation as specified was not in fact implementable. The
+ -- operation was changed from an entry to a protected procedure per the
+ -- ARG meeting in Edinburgh (June 2011), with a different signature and
+ -- semantics.
- overriding
- function Current_Use return Count_Type;
+ not overriding
+ procedure Dequeue_Only_High_Priority
+ (At_Least : Queue_Priority;
+ Element : in out Queue_Interfaces.Element_Type;
+ Success : out Boolean);
- overriding
- function Peak_Use return Count_Type;
+ overriding
+ function Current_Use return Count_Type;
+
+ overriding
+ function Peak_Use return Count_Type;
private
diff --git a/gcc/ada/a-cusyqu.ads b/gcc/ada/a-cusyqu.ads
index 98337a03587..c4f9d7f7d59 100644
--- a/gcc/ada/a-cusyqu.ads
+++ b/gcc/ada/a-cusyqu.ads
@@ -44,11 +44,11 @@ generic
package Ada.Containers.Unbounded_Synchronized_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type is tagged limited private;
@@ -86,9 +86,7 @@ package Ada.Containers.Unbounded_Synchronized_Queues is
end Implementation;
protected type Queue (Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
overriding
entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
diff --git a/gcc/ada/a-ngcoar.adb b/gcc/ada/a-ngcoar.adb
index 9979d6baec6..3be88491d7f 100644
--- a/gcc/ada/a-ngcoar.adb
+++ b/gcc/ada/a-ngcoar.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2006-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 2006-2011, 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- --
@@ -30,66 +30,35 @@
------------------------------------------------------------------------------
with System.Generic_Array_Operations; use System.Generic_Array_Operations;
-with System.Generic_Complex_BLAS;
-with System.Generic_Complex_LAPACK;
+with Ada.Numerics; use Ada.Numerics;
package body Ada.Numerics.Generic_Complex_Arrays is
- -- Operations involving inner products use BLAS library implementations.
- -- This allows larger matrices and vectors to be computed efficiently,
- -- taking into account memory hierarchy issues and vector instructions
- -- that vary widely between machines.
-
-- Operations that are defined in terms of operations on the type Real,
-- such as addition, subtraction and scaling, are computed in the canonical
-- way looping over all elements.
- -- Operations for solving linear systems and computing determinant,
- -- eigenvalues, eigensystem and inverse, are implemented using the
- -- LAPACK library.
-
- type BLAS_Real_Vector is array (Integer range <>) of Real;
-
- package BLAS is new System.Generic_Complex_BLAS
- (Real => Real,
- Complex_Types => Complex_Types,
- Complex_Vector => Complex_Vector,
- Complex_Matrix => Complex_Matrix);
-
- package LAPACK is new System.Generic_Complex_LAPACK
- (Real => Real,
- Real_Vector => BLAS_Real_Vector,
- Complex_Types => Complex_Types,
- Complex_Vector => Complex_Vector,
- Complex_Matrix => Complex_Matrix);
+ package Ops renames System.Generic_Array_Operations;
subtype Real is Real_Arrays.Real;
-- Work around visibility bug ???
- use BLAS, LAPACK;
-
- -- Procedure versions of functions returning unconstrained values.
- -- This allows for inlining the function wrapper.
+ function Is_Non_Zero (X : Complex) return Boolean is (X /= (0.0, 0.0));
+ -- Needed by Back_Substitute
- procedure Eigenvalues
- (A : Complex_Matrix;
- Values : out Real_Vector);
+ procedure Back_Substitute is new Ops.Back_Substitute
+ (Scalar => Complex,
+ Matrix => Complex_Matrix,
+ Is_Non_Zero => Is_Non_Zero);
- procedure Inverse
- (A : Complex_Matrix;
- R : out Complex_Matrix);
+ procedure Forward_Eliminate is new Ops.Forward_Eliminate
+ (Scalar => Complex,
+ Real => Real'Base,
+ Matrix => Complex_Matrix,
+ Zero => (0.0, 0.0),
+ One => (1.0, 0.0));
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Vector;
- B : out Complex_Vector);
-
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Matrix;
- B : out Complex_Matrix);
-
- procedure Transpose is new System.Generic_Array_Operations.Transpose
+ procedure Transpose is new Ops.Transpose
(Scalar => Complex,
Matrix => Complex_Matrix);
@@ -98,6 +67,12 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function Length is new Square_Matrix_Length (Complex, Complex_Matrix);
+ -- Instant a generic square root implementation here, in order to avoid
+ -- instantiating a complete copy of Generic_Elementary_Functions.
+ -- Speed of the square root is not a big concern here.
+
+ function Sqrt is new Ops.Sqrt (Real'Base);
+
-- Instantiating the following subprograms directly would lead to
-- name clashes, so use a local package.
@@ -155,6 +130,14 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Right_Vector => Complex_Vector,
Zero => (0.0, 0.0));
+ function "*" is new Inner_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Left_Vector => Complex_Vector,
+ Right_Vector => Complex_Vector,
+ Zero => (0.0, 0.0));
+
function "*" is new Outer_Product
(Left_Scalar => Complex,
Right_Scalar => Complex,
@@ -229,6 +212,15 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Result_Vector => Complex_Vector,
Zero => (0.0, 0.0));
+ function "*" is new Matrix_Vector_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Matrix => Complex_Matrix,
+ Right_Vector => Complex_Vector,
+ Result_Vector => Complex_Vector,
+ Zero => (0.0, 0.0));
+
function "*" is new Vector_Matrix_Product
(Left_Scalar => Real'Base,
Right_Scalar => Complex,
@@ -247,6 +239,24 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Result_Vector => Complex_Vector,
Zero => (0.0, 0.0));
+ function "*" is new Vector_Matrix_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Left_Vector => Complex_Vector,
+ Matrix => Complex_Matrix,
+ Result_Vector => Complex_Vector,
+ Zero => (0.0, 0.0));
+
+ function "*" is new Matrix_Matrix_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Left_Matrix => Complex_Matrix,
+ Right_Matrix => Complex_Matrix,
+ Result_Matrix => Complex_Matrix,
+ Zero => (0.0, 0.0));
+
function "*" is new Matrix_Matrix_Product
(Left_Scalar => Real'Base,
Right_Scalar => Complex,
@@ -445,6 +455,15 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Result_Matrix => Complex_Matrix,
Operation => "/");
+ -----------
+ -- "abs" --
+ -----------
+
+ function "abs" is new L2_Norm
+ (X_Scalar => Complex,
+ Result_Real => Real'Base,
+ X_Vector => Complex_Vector);
+
--------------
-- Argument --
--------------
@@ -671,6 +690,16 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Y_Matrix => Real_Matrix,
Update => Set_Re);
+ -----------
+ -- Solve --
+ -----------
+
+ function Solve is
+ new Matrix_Vector_Solution (Complex, Complex_Vector, Complex_Matrix);
+
+ function Solve is
+ new Matrix_Matrix_Solution (Complex, Complex_Matrix);
+
-----------------
-- Unit_Matrix --
-----------------
@@ -686,7 +715,6 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Vector => Complex_Vector,
Zero => (0.0, 0.0),
One => (1.0, 0.0));
-
end Instantiations;
---------
@@ -696,15 +724,7 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function "*"
(Left : Complex_Vector;
Right : Complex_Vector) return Complex
- is
- begin
- if Left'Length /= Right'Length then
- raise Constraint_Error with
- "vectors are of different length in inner product";
- end if;
-
- return dot (Left'Length, X => Left, Y => Right);
- end "*";
+ renames Instantiations."*";
function "*"
(Left : Real_Vector;
@@ -738,31 +758,8 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function "*"
(Left : Complex_Matrix;
- Right : Complex_Matrix)
- return Complex_Matrix
- is
- R : Complex_Matrix (Left'Range (1), Right'Range (2));
-
- begin
- if Left'Length (2) /= Right'Length (1) then
- raise Constraint_Error with
- "incompatible dimensions in matrix-matrix multiplication";
- end if;
-
- gemm (Trans_A => No_Trans'Access,
- Trans_B => No_Trans'Access,
- M => Right'Length (2),
- N => Left'Length (1),
- K => Right'Length (1),
- A => Right,
- Ld_A => Right'Length (2),
- B => Left,
- Ld_B => Left'Length (2),
- C => R,
- Ld_C => R'Length (2));
-
- return R;
- end "*";
+ Right : Complex_Matrix) return Complex_Matrix
+ renames Instantiations."*";
function "*"
(Left : Complex_Vector;
@@ -772,48 +769,12 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function "*"
(Left : Complex_Vector;
Right : Complex_Matrix) return Complex_Vector
- is
- R : Complex_Vector (Right'Range (2));
-
- begin
- if Left'Length /= Right'Length (1) then
- raise Constraint_Error with
- "incompatible dimensions in vector-matrix multiplication";
- end if;
-
- gemv (Trans => No_Trans'Access,
- M => Right'Length (2),
- N => Right'Length (1),
- A => Right,
- Ld_A => Right'Length (2),
- X => Left,
- Y => R);
-
- return R;
- end "*";
+ renames Instantiations."*";
function "*"
(Left : Complex_Matrix;
Right : Complex_Vector) return Complex_Vector
- is
- R : Complex_Vector (Left'Range (1));
-
- begin
- if Left'Length (2) /= Right'Length then
- raise Constraint_Error with
- "incompatible dimensions in matrix-vector multiplication";
- end if;
-
- gemv (Trans => Trans'Access,
- M => Left'Length (2),
- N => Left'Length (1),
- A => Left,
- Ld_A => Left'Length (2),
- X => Right,
- Y => R);
-
- return R;
- end "*";
+ renames Instantiations."*";
function "*"
(Left : Real_Matrix;
@@ -984,10 +945,8 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-- "abs" --
-----------
- function "abs" (Right : Complex_Vector) return Complex is
- begin
- return (nrm2 (Right'Length, Right), 0.0);
- end "abs";
+ function "abs" (Right : Complex_Vector) return Real'Base
+ renames Instantiations."abs";
--------------
-- Argument --
@@ -1070,38 +1029,12 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-----------------
function Determinant (A : Complex_Matrix) return Complex is
- N : constant Integer := Length (A);
- LU : Complex_Matrix (1 .. N, 1 .. N) := A;
- Piv : Integer_Vector (1 .. N);
- Info : aliased Integer := -1;
- Neg : Boolean;
- Det : Complex;
-
+ M : Complex_Matrix := A;
+ B : Complex_Matrix (A'Range (1), 1 .. 0);
+ R : Complex;
begin
- if N = 0 then
- return (0.0, 0.0);
- end if;
-
- getrf (N, N, LU, N, Piv, Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "ill-conditioned matrix";
- end if;
-
- Det := LU (1, 1);
- Neg := Piv (1) /= 1;
-
- for J in 2 .. N loop
- Det := Det * LU (J, J);
- Neg := Neg xor (Piv (J) /= J);
- end loop;
-
- if Neg then
- return -Det;
-
- else
- return Det;
- end if;
+ Forward_Eliminate (M, B, R);
+ return R;
end Determinant;
-----------------
@@ -1113,174 +1046,96 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Values : out Real_Vector;
Vectors : out Complex_Matrix)
is
- Job_Z : aliased Character := 'V';
- Rng : aliased Character := 'A';
- Uplo : aliased Character := 'U';
-
- N : constant Natural := Length (A);
- W : BLAS_Real_Vector (Values'Range);
- M : Integer;
- B : Complex_Matrix (1 .. N, 1 .. N);
- L_Work : Complex_Vector (1 .. 1);
- LR_Work : BLAS_Real_Vector (1 .. 1);
- LI_Work : Integer_Vector (1 .. 1);
- I_Supp_Z : Integer_Vector (1 .. 2 * N);
- Info : aliased Integer;
+ N : constant Natural := Length (A);
+
+ -- For a Hermitian matrix C, we convert the eigenvalue problem to a
+ -- real symmetric one: if C = A + i * B, then the (N, N) complex
+ -- eigenvalue problem:
+ -- (A + i * B) * (u + i * v) = Lambda * (u + i * v)
+ --
+ -- is equivalent to the (2 * N, 2 * N) real eigenvalue problem:
+ -- [ A, B ] [ u ] = Lambda * [ u ]
+ -- [ -B, A ] [ v ] [ v ]
+ --
+ -- Note that the (2 * N, 2 * N) matrix above is symmetric, as
+ -- Transpose (A) = A and Transpose (B) = -B if C is Hermitian.
+
+ -- We solve this eigensystem using the real-valued algorithms. The final
+ -- result will have every eigenvalue twice, so in the sorted output we
+ -- just pick every second value, with associated eigenvector u + i * v.
+
+ M : Real_Matrix (1 .. 2 * N, 1 .. 2 * N);
+ Vals : Real_Vector (1 .. 2 * N);
+ Vecs : Real_Matrix (1 .. 2 * N, 1 .. 2 * N);
begin
- if Values'Length /= N then
- raise Constraint_Error with "wrong length for output vector";
- end if;
-
- if Vectors'First (1) /= A'First (1)
- or else Vectors'Last (1) /= A'Last (1)
- or else Vectors'First (2) /= A'First (2)
- or else Vectors'Last (2) /= A'Last (2)
- then
- raise Constraint_Error with "wrong dimensions for output matrix";
- end if;
-
- if N = 0 then
- return;
- end if;
-
- -- Check for hermitian matrix ???
- -- Copy only required triangle ???
-
- B := A;
-
- -- Find size of work area
-
- heevr
- (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Vectors,
- Ld_Z => N,
- I_Supp_Z => I_Supp_Z,
- Work => L_Work,
- L_Work => -1,
- R_Work => LR_Work,
- LR_Work => -1,
- I_Work => LI_Work,
- LI_Work => -1,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error;
- end if;
-
- declare
- Work : Complex_Vector (1 .. Integer (L_Work (1).Re));
- R_Work : BLAS_Real_Vector (1 .. Integer (LR_Work (1)));
- I_Work : Integer_Vector (1 .. LI_Work (1));
-
- begin
- heevr
- (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Vectors,
- Ld_Z => N,
- I_Supp_Z => I_Supp_Z,
- Work => Work,
- L_Work => Work'Length,
- R_Work => R_Work,
- LR_Work => LR_Work'Length,
- I_Work => I_Work,
- LI_Work => LI_Work'Length,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting non-Hermitian matrix";
- end if;
-
- for J in Values'Range loop
- Values (J) := W (J);
+ for J in 1 .. N loop
+ for K in 1 .. N loop
+ declare
+ C : constant Complex :=
+ (A (A'First (1) + (J - 1), A'First (2) + (K - 1)));
+ begin
+ M (J, K) := Re (C);
+ M (J + N, K + N) := Re (C);
+ M (J + N, K) := Im (C);
+ M (J, K + N) := -Im (C);
+ end;
end loop;
- end;
+ end loop;
+
+ Eigensystem (M, Vals, Vecs);
+
+ for J in 1 .. N loop
+ declare
+ Col : constant Integer := Values'First + (J - 1);
+ begin
+ Values (Col) := Vals (2 * J);
+
+ for K in 1 .. N loop
+ declare
+ Row : constant Integer := Vectors'First (2) + (K - 1);
+ begin
+ Vectors (Row, Col)
+ := (Vecs (J * 2, Col), Vecs (J * 2, Col + N));
+ end;
+ end loop;
+ end;
+ end loop;
end Eigensystem;
-----------------
-- Eigenvalues --
-----------------
- procedure Eigenvalues
- (A : Complex_Matrix;
- Values : out Real_Vector)
- is
- Job_Z : aliased Character := 'N';
- Rng : aliased Character := 'A';
- Uplo : aliased Character := 'U';
- N : constant Natural := Length (A);
- B : Complex_Matrix (1 .. N, 1 .. N) := A;
- Z : Complex_Matrix (1 .. 1, 1 .. 1);
- W : BLAS_Real_Vector (Values'Range);
- L_Work : Complex_Vector (1 .. 1);
- LR_Work : BLAS_Real_Vector (1 .. 1);
- LI_Work : Integer_Vector (1 .. 1);
- I_Supp_Z : Integer_Vector (1 .. 2 * N);
- M : Integer;
- Info : aliased Integer;
+ function Eigenvalues (A : Complex_Matrix) return Real_Vector is
+ -- See Eigensystem for a description of the algorithm
+ N : constant Natural := Length (A);
+ R : Real_Vector (A'Range (1));
+
+ M : Real_Matrix (1 .. 2 * N, 1 .. 2 * N);
+ Vals : Real_Vector (1 .. 2 * N);
begin
- if Values'Length /= N then
- raise Constraint_Error with "wrong length for output vector";
- end if;
-
- if N = 0 then
- return;
- end if;
-
- -- Check for hermitian matrix ???
-
- -- Find size of work area
-
- heevr (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Z,
- Ld_Z => 1,
- I_Supp_Z => I_Supp_Z,
- Work => L_Work, L_Work => -1,
- R_Work => LR_Work, LR_Work => -1,
- I_Work => LI_Work, LI_Work => -1,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error;
- end if;
-
- declare
- Work : Complex_Vector (1 .. Integer (L_Work (1).Re));
- R_Work : BLAS_Real_Vector (1 .. Integer (LR_Work (1)));
- I_Work : Integer_Vector (1 .. LI_Work (1));
- begin
- heevr (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Z,
- Ld_Z => 1,
- I_Supp_Z => I_Supp_Z,
- Work => Work, L_Work => Work'Length,
- R_Work => R_Work, LR_Work => R_Work'Length,
- I_Work => I_Work, LI_Work => I_Work'Length,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting singular matrix";
- end if;
-
- for J in Values'Range loop
- Values (J) := W (J);
+ for J in 1 .. N loop
+ for K in 1 .. N loop
+ declare
+ C : constant Complex :=
+ (A (A'First (1) + (J - 1), A'First (2) + (K - 1)));
+ begin
+ M (J, K) := Re (C);
+ M (J + N, K + N) := Re (C);
+ M (J + N, K) := Im (C);
+ M (J, K + N) := -Im (C);
+ end;
end loop;
- end;
- end Eigenvalues;
+ end loop;
+
+ Vals := Eigenvalues (M);
+
+ for J in 1 .. N loop
+ R (A'First (1) + (J - 1)) := Vals (2 * J);
+ end loop;
- function Eigenvalues (A : Complex_Matrix) return Real_Vector is
- R : Real_Vector (A'Range (1));
- begin
- Eigenvalues (A, R);
return R;
end Eigenvalues;
@@ -1298,73 +1153,8 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-- Inverse --
-------------
- procedure Inverse (A : Complex_Matrix; R : out Complex_Matrix) is
- N : constant Integer := Length (A);
- Piv : Integer_Vector (1 .. N);
- L_Work : Complex_Vector (1 .. 1);
- Info : aliased Integer := -1;
-
- begin
- -- All computations are done using column-major order, but this works
- -- out fine, because Transpose (Inverse (Transpose (A))) = Inverse (A).
-
- R := A;
-
- -- Compute LU decomposition
-
- getrf (M => N,
- N => N,
- A => R,
- Ld_A => N,
- I_Piv => Piv,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting singular matrix";
- end if;
-
- -- Determine size of work area
-
- getri (N => N,
- A => R,
- Ld_A => N,
- I_Piv => Piv,
- Work => L_Work,
- L_Work => -1,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error;
- end if;
-
- declare
- Work : Complex_Vector (1 .. Integer (L_Work (1).Re));
-
- begin
- -- Compute inverse from LU decomposition
-
- getri (N => N,
- A => R,
- Ld_A => N,
- I_Piv => Piv,
- Work => Work,
- L_Work => Work'Length,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting singular matrix";
- end if;
-
- -- ??? Should iterate with gerfs, based on implementation advice
- end;
- end Inverse;
-
function Inverse (A : Complex_Matrix) return Complex_Matrix is
- R : Complex_Matrix (A'Range (2), A'Range (1));
- begin
- Inverse (A, R);
- return R;
- end Inverse;
+ (Solve (A, Unit_Matrix (Length (A))));
-------------
-- Modulus --
@@ -1418,53 +1208,15 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-- Solve --
-----------
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Vector;
- B : out Complex_Vector)
- is
- begin
- if Length (A) /= X'Length then
- raise Constraint_Error with
- "incompatible matrix and vector dimensions";
- end if;
-
- -- ??? Should solve directly, is faster and more accurate
-
- B := Inverse (A) * X;
- end Solve;
-
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Matrix;
- B : out Complex_Matrix)
- is
- begin
- if Length (A) /= X'Length (1) then
- raise Constraint_Error with "incompatible matrix dimensions";
- end if;
-
- -- ??? Should solve directly, is faster and more accurate
-
- B := Inverse (A) * X;
- end Solve;
-
function Solve
(A : Complex_Matrix;
X : Complex_Vector) return Complex_Vector
- is
- B : Complex_Vector (A'Range (2));
- begin
- Solve (A, X, B);
- return B;
- end Solve;
+ renames Instantiations.Solve;
- function Solve (A, X : Complex_Matrix) return Complex_Matrix is
- B : Complex_Matrix (A'Range (2), X'Range (2));
- begin
- Solve (A, X, B);
- return B;
- end Solve;
+ function Solve
+ (A : Complex_Matrix;
+ X : Complex_Matrix) return Complex_Matrix
+ renames Instantiations.Solve;
---------------
-- Transpose --
diff --git a/gcc/ada/a-ngcoar.ads b/gcc/ada/a-ngcoar.ads
index abffbd1b636..8f8f37a7906 100644
--- a/gcc/ada/a-ngcoar.ads
+++ b/gcc/ada/a-ngcoar.ads
@@ -66,7 +66,7 @@ package Ada.Numerics.Generic_Complex_Arrays is
function "+" (Left, Right : Complex_Vector) return Complex_Vector;
function "-" (Left, Right : Complex_Vector) return Complex_Vector;
function "*" (Left, Right : Complex_Vector) return Complex;
- function "abs" (Right : Complex_Vector) return Complex;
+ function "abs" (Right : Complex_Vector) return Real'Base;
-- Mixed Real_Vector and Complex_Vector arithmetic operations
diff --git a/gcc/ada/a-ngrear.adb b/gcc/ada/a-ngrear.adb
index 8ce8d9a98b0..2a740b5c6b4 100644
--- a/gcc/ada/a-ngrear.adb
+++ b/gcc/ada/a-ngrear.adb
@@ -33,7 +33,7 @@
-- reason for this is new Ada 2012 requirements that prohibit algorithms such
-- as Strassen's algorithm, which may be used by some BLAS implementations. In
-- addition, some platforms lacked suitable compilers to compile the reference
--- BLAS/LAPACK implementation. Finally, on many platforms there may be more
+-- BLAS/LAPACK implementation. Finally, on some platforms there are more
-- floating point types than supported by BLAS/LAPACK.
with Ada.Containers.Generic_Anonymous_Array_Sort; use Ada.Containers;
@@ -59,6 +59,7 @@ package body Ada.Numerics.Generic_Real_Arrays is
procedure Forward_Eliminate is new Ops.Forward_Eliminate
(Scalar => Real'Base,
+ Real => Real'Base,
Matrix => Real_Matrix,
Zero => 0.0,
One => 1.0);
@@ -102,10 +103,10 @@ package body Ada.Numerics.Generic_Real_Arrays is
procedure Swap (Left, Right : in out Real);
-- Exchange Left and Right
- function Sqrt (X : Real) return Real;
- -- Sqrt is implemented locally here, in order to avoid dragging in all of
- -- the elementary functions. Speed of the square root is not a big concern
- -- here. This also avoids depending on a specific floating point type.
+ function Sqrt is new Ops.Sqrt (Real);
+ -- Instant a generic square root implementation here, in order to avoid
+ -- instantiating a complete copy of Generic_Elementary_Functions.
+ -- Speed of the square root is not a big concern here.
------------
-- Rotate --
@@ -120,51 +121,6 @@ package body Ada.Numerics.Generic_Real_Arrays is
end Rotate;
----------
- -- Sqrt --
- ----------
-
- function Sqrt (X : Real) return Real is
- Root, Next : Real;
-
- begin
- -- Be defensive: any comparisons with NaN values will yield False.
-
- if not (X > 0.0) then
- if X = 0.0 then
- return X;
- else
- raise Argument_Error;
- end if;
- end if;
-
- -- Compute an initial estimate based on:
-
- -- X = M * R**E and Sqrt (X) = Sqrt (M) * R**(E / 2.0),
-
- -- where M is the mantissa, R is the radix and E the exponent.
-
- -- By ignoring the mantissa and ignoring the case of an odd
- -- exponent, we get a final error that is at most R. In other words,
- -- the result has about a single bit precision.
-
- Root := Real (Real'Machine_Radix) ** (Real'Exponent (X) / 2);
-
- -- Because of the poor initial estimate, use the Babylonian method of
- -- computing the square root, as it is stable for all inputs. Every step
- -- will roughly double the precision of the result. Just a few steps
- -- suffice in most cases. Eight iterations should give about 2**8 bits
- -- of precision.
-
- for J in 1 .. 8 loop
- Next := (Root + X / Root) / 2.0;
- exit when Root = Next;
- Root := Next;
- end loop;
-
- return Root;
- end Sqrt;
-
- ----------
-- Swap --
----------
@@ -356,10 +312,14 @@ package body Ada.Numerics.Generic_Real_Arrays is
function "abs" is new
L2_Norm
- (Scalar => Real'Base,
- Vector => Real_Vector,
- Inner_Product => "*",
- Sqrt => Sqrt);
+ (X_Scalar => Real'Base,
+ Result_Real => Real'Base,
+ X_Vector => Real_Vector,
+ "abs" => "+");
+ -- While the L2_Norm by definition uses the absolute values of the
+ -- elements of X_Vector, for real values the subsequent squaring
+ -- makes this unnecessary, so we substitute the "+" identity function
+ -- instead.
function "abs" is new
Vector_Elementwise_Operation
@@ -377,6 +337,11 @@ package body Ada.Numerics.Generic_Real_Arrays is
Result_Matrix => Real_Matrix,
Operation => "abs");
+ function Solve is
+ new Matrix_Vector_Solution (Real'Base, Real_Vector, Real_Matrix);
+
+ function Solve is new Matrix_Matrix_Solution (Real'Base, Real_Matrix);
+
function Unit_Matrix is new
Generic_Array_Operations.Unit_Matrix
(Scalar => Real'Base,
@@ -736,58 +701,11 @@ package body Ada.Numerics.Generic_Real_Arrays is
-- Solve --
-----------
- function Solve (A : Real_Matrix; X : Real_Vector) return Real_Vector is
- N : constant Natural := Length (A);
- MA : Real_Matrix := A;
- MX : Real_Matrix (A'Range (1), 1 .. 1);
- R : Real_Vector (A'Range (2));
- Det : Real'Base;
-
- begin
- if X'Length /= N then
- raise Constraint_Error with "incompatible vector length";
- end if;
-
- for J in 0 .. MX'Length (1) - 1 loop
- MX (MX'First (1) + J, 1) := X (X'First + J);
- end loop;
-
- Forward_Eliminate (MA, MX, Det);
- Back_Substitute (MA, MX);
-
- for J in 0 .. R'Length - 1 loop
- R (R'First + J) := MX (MX'First (1) + J, 1);
- end loop;
-
- return R;
- end Solve;
-
- function Solve (A, X : Real_Matrix) return Real_Matrix is
- N : constant Natural := Length (A);
- MA : Real_Matrix (A'Range (2), A'Range (2));
- MB : Real_Matrix (A'Range (2), X'Range (2));
- Det : Real'Base;
-
- begin
- if X'Length (1) /= N then
- raise Constraint_Error with "matrices have unequal number of rows";
- end if;
-
- for J in 0 .. A'Length (1) - 1 loop
- for K in MA'Range (2) loop
- MA (MA'First (1) + J, K) := A (A'First (1) + J, K);
- end loop;
-
- for K in MB'Range (2) loop
- MB (MB'First (1) + J, K) := X (X'First (1) + J, K);
- end loop;
- end loop;
-
- Forward_Eliminate (MA, MB, Det);
- Back_Substitute (MA, MB);
+ function Solve (A : Real_Matrix; X : Real_Vector) return Real_Vector
+ renames Instantiations.Solve;
- return MB;
- end Solve;
+ function Solve (A, X : Real_Matrix) return Real_Matrix
+ renames Instantiations.Solve;
----------------------
-- Sort_Eigensystem --
diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb
index f5a2bdcecad..d75fe06c51b 100644
--- a/gcc/ada/bindgen.adb
+++ b/gcc/ada/bindgen.adb
@@ -1893,25 +1893,6 @@ package body Bindgen is
Write_Str (Name_Buffer (1 .. Name_Len));
Write_Eol;
end if;
-
- -- Don't link with the shared library on VMS if an internal
- -- filename object is seen. Multiply defined symbols will
- -- result.
-
- if OpenVMS_On_Target
- and then Is_Internal_File_Name
- (ALIs.Table
- (Units.Table (Elab_Order.Table (E)).My_ALI).Sfile)
- then
- -- Special case for g-trasym.obj (not included in libgnat)
-
- Get_Name_String (ALIs.Table
- (Units.Table (Elab_Order.Table (E)).My_ALI).Sfile);
-
- if Name_Buffer (1 .. 8) /= "g-trasym" then
- Opt.Shared_Libgnat := False;
- end if;
- end if;
end if;
end if;
end loop;
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 93d914fd855..019f2f37133 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -2475,11 +2475,11 @@ package Einfo is
-- Is_Local_Anonymous_Access (Flag194)
-- Present in access types. Set for an anonymous access type to indicate
-- that the type is created for a record component with an access
--- definition, an array component, or (pre-Ada2012) a stand-alone object.
+-- definition, an array component, or (pre-Ada 2012) a standalone object.
-- Such anonymous types have an accessibility level equal to that of the
-- declaration in which they appear, unlike the anonymous access types
-- that are created for access parameters, access discriminants, and
--- (as of Ada2012) stand-alone objects.
+-- (as of Ada 2012) stand-alone objects.
-- Is_Machine_Code_Subprogram (Flag137)
-- Present in subprogram entities. Set to indicate that the subprogram
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index d06d8b9fb54..783772f0188 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -3398,6 +3398,15 @@ package body Exp_Aggr is
begin
Assoc := First (Component_Associations (N));
while Present (Assoc) loop
+
+ -- If this is a box association, flattening is in general
+ -- not possible because at this point we cannot tell if the
+ -- default is static or even exists.
+
+ if Box_Present (Assoc) then
+ return False;
+ end if;
+
Choice := First (Choices (Assoc));
while Present (Choice) loop
@@ -3506,7 +3515,7 @@ package body Exp_Aggr is
-- active, if this is a preelaborable unit or a
-- predefined unit. This ensures that predefined
-- units get the same level of constant folding in
- -- Ada 95 and Ada 05, where their categorization
+ -- Ada 95 and Ada 2005, where their categorization
-- has changed.
declare
@@ -4148,6 +4157,12 @@ package body Exp_Aggr is
return False;
end if;
+ -- If association has a box, no way to determine yet
+ -- whether default can be assigned in place.
+
+ elsif Box_Present (Expr) then
+ return False;
+
elsif not Safe_Component (Expression (Expr)) then
return False;
end if;
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index 897844bb8e4..db8f6a30d5d 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -678,7 +678,7 @@ package body Exp_Attr is
case Id is
- -- Attributes related to Ada2012 iterators (placeholder ???)
+ -- Attributes related to Ada 2012 iterators (placeholder ???)
when Attribute_Constant_Indexing => null;
when Attribute_Default_Iterator => null;
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index fecbf5ce26b..5f413e31bd3 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -114,20 +114,6 @@ package body Exp_Ch3 is
-- removing the implicit call that would otherwise constitute elaboration
-- code.
- function Build_Master_Renaming
- (N : Node_Id;
- T : Entity_Id) return Entity_Id;
- -- If the designated type of an access type is a task type or contains
- -- tasks, we make sure that a _Master variable is declared in the current
- -- scope, and then declare a renaming for it:
- --
- -- atypeM : Master_Id renames _Master;
- --
- -- where atyp is the name of the access type. This declaration is used when
- -- an allocator for the access type is expanded. The node is the full
- -- declaration of the designated type that contains tasks. The renaming
- -- declaration is inserted before N, and after the Master declaration.
-
procedure Build_Record_Init_Proc (N : Node_Id; Rec_Ent : Entity_Id);
-- Build record initialization procedure. N is the type declaration
-- node, and Rec_Ent is the corresponding entity for the record type.
@@ -777,132 +763,6 @@ package body Exp_Ch3 is
end if;
end Build_Array_Init_Proc;
- -----------------------------
- -- Build_Class_Wide_Master --
- -----------------------------
-
- procedure Build_Class_Wide_Master (T : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (T);
- Master_Id : Entity_Id;
- Master_Scope : Entity_Id;
- Name_Id : Node_Id;
- Related_Node : Node_Id;
- Ren_Decl : Node_Id;
-
- begin
- -- Nothing to do if there is no task hierarchy
-
- if Restriction_Active (No_Task_Hierarchy) then
- return;
- end if;
-
- -- Find the declaration that created the access type. It is either a
- -- type declaration, or an object declaration with an access definition,
- -- in which case the type is anonymous.
-
- if Is_Itype (T) then
- Related_Node := Associated_Node_For_Itype (T);
- else
- Related_Node := Parent (T);
- end if;
-
- Master_Scope := Find_Master_Scope (T);
-
- -- Nothing to do if the master scope already contains a _master entity.
- -- The only exception to this is the following scenario:
-
- -- Source_Scope
- -- Transient_Scope_1
- -- _master
-
- -- Transient_Scope_2
- -- use of master
-
- -- In this case the source scope is marked as having the master entity
- -- even though the actual declaration appears inside an inner scope. If
- -- the second transient scope requires a _master, it cannot use the one
- -- already declared because the entity is not visible.
-
- Name_Id := Make_Identifier (Loc, Name_uMaster);
-
- if not Has_Master_Entity (Master_Scope)
- or else No (Current_Entity_In_Scope (Name_Id))
- then
- declare
- Master_Decl : Node_Id;
-
- begin
- Set_Has_Master_Entity (Master_Scope);
-
- -- Generate:
- -- _master : constant Integer := Current_Master.all;
-
- Master_Decl :=
- Make_Object_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_uMaster),
- Constant_Present => True,
- Object_Definition =>
- New_Reference_To (Standard_Integer, Loc),
- Expression =>
- Make_Explicit_Dereference (Loc,
- New_Reference_To (RTE (RE_Current_Master), Loc)));
-
- Insert_Action (Related_Node, Master_Decl);
- Analyze (Master_Decl);
-
- -- Mark the containing scope as a task master. Masters associated
- -- with return statements are already marked at this stage (see
- -- Analyze_Subprogram_Body).
-
- if Ekind (Current_Scope) /= E_Return_Statement then
- declare
- Par : Node_Id := Related_Node;
-
- begin
- while Nkind (Par) /= N_Compilation_Unit loop
- Par := Parent (Par);
-
- -- If we fall off the top, we are at the outer level, and
- -- the environment task is our effective master, so
- -- nothing to mark.
-
- if Nkind_In (Par, N_Block_Statement,
- N_Subprogram_Body,
- N_Task_Body)
- then
- Set_Is_Task_Master (Par);
- exit;
- end if;
- end loop;
- end;
- end if;
- end;
- end if;
-
- Master_Id :=
- Make_Defining_Identifier (Loc,
- New_External_Name (Chars (T), 'M'));
-
- -- Generate:
- -- Mnn renames _master;
-
- Ren_Decl :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier => Master_Id,
- Subtype_Mark => New_Reference_To (Standard_Integer, Loc),
- Name => Name_Id);
-
- Insert_Before (Related_Node, Ren_Decl);
- Analyze (Ren_Decl);
-
- Set_Master_Id (T, Master_Id);
-
- exception
- when RE_Not_Available =>
- return;
- end Build_Class_Wide_Master;
-
--------------------------------
-- Build_Discr_Checking_Funcs --
--------------------------------
@@ -1673,65 +1533,6 @@ package body Exp_Ch3 is
return Empty_List;
end Build_Initialization_Call;
- ---------------------------
- -- Build_Master_Renaming --
- ---------------------------
-
- function Build_Master_Renaming
- (N : Node_Id;
- T : Entity_Id) return Entity_Id
- is
- Loc : constant Source_Ptr := Sloc (N);
- M_Id : Entity_Id;
- Decl : Node_Id;
-
- begin
- -- Nothing to do if there is no task hierarchy
-
- if Restriction_Active (No_Task_Hierarchy) then
- return Empty;
- end if;
-
- M_Id :=
- Make_Defining_Identifier (Loc,
- New_External_Name (Chars (T), 'M'));
-
- Decl :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier => M_Id,
- Subtype_Mark => New_Reference_To (RTE (RE_Master_Id), Loc),
- Name => Make_Identifier (Loc, Name_uMaster));
- Insert_Before (N, Decl);
- Analyze (Decl);
- return M_Id;
-
- exception
- when RE_Not_Available =>
- return Empty;
- end Build_Master_Renaming;
-
- ---------------------------
- -- Build_Master_Renaming --
- ---------------------------
-
- procedure Build_Master_Renaming (N : Node_Id; T : Entity_Id) is
- M_Id : Entity_Id;
-
- begin
- -- Nothing to do if there is no task hierarchy
-
- if Restriction_Active (No_Task_Hierarchy) then
- return;
- end if;
-
- M_Id := Build_Master_Renaming (N, T);
- Set_Master_Id (T, M_Id);
-
- exception
- when RE_Not_Available =>
- return;
- end Build_Master_Renaming;
-
----------------------------
-- Build_Record_Init_Proc --
----------------------------
@@ -4323,29 +4124,27 @@ package body Exp_Ch3 is
------------------------------------
procedure Expand_N_Full_Type_Declaration (N : Node_Id) is
- Def_Id : constant Entity_Id := Defining_Identifier (N);
- B_Id : constant Entity_Id := Base_Type (Def_Id);
- Par_Id : Entity_Id;
- FN : Node_Id;
- procedure Build_Master (Def_Id : Entity_Id);
- -- Create the master associated with Def_Id
+ procedure Build_Master (Ptr_Typ : Entity_Id);
+ -- Create the master associated with Ptr_Typ
------------------
-- Build_Master --
------------------
- procedure Build_Master (Def_Id : Entity_Id) is
+ procedure Build_Master (Ptr_Typ : Entity_Id) is
+ Desig_Typ : constant Entity_Id := Designated_Type (Ptr_Typ);
+
begin
-- Anonymous access types are created for the components of the
-- record parameter for an entry declaration. No master is created
-- for such a type.
- if Has_Task (Designated_Type (Def_Id))
- and then Comes_From_Source (N)
+ if Comes_From_Source (N)
+ and then Has_Task (Desig_Typ)
then
- Build_Master_Entity (Def_Id);
- Build_Master_Renaming (Parent (Def_Id), Def_Id);
+ Build_Master_Entity (Ptr_Typ);
+ Build_Master_Renaming (Ptr_Typ);
-- Create a class-wide master because a Master_Id must be generated
-- for access-to-limited-class-wide types whose root may be extended
@@ -4354,32 +4153,38 @@ package body Exp_Ch3 is
-- Note: This code covers access-to-limited-interfaces because they
-- can be used to reference tasks implementing them.
- elsif Is_Class_Wide_Type (Designated_Type (Def_Id))
- and then Is_Limited_Type (Designated_Type (Def_Id))
+ elsif Is_Limited_Class_Wide_Type (Desig_Typ)
and then Tasking_Allowed
- -- Do not create a class-wide master for types whose convention is
- -- Java since these types cannot embed Ada tasks anyway. Note that
- -- the following test cannot catch the following case:
+ -- Do not create a class-wide master for types whose convention is
+ -- Java since these types cannot embed Ada tasks anyway. Note that
+ -- the following test cannot catch the following case:
- -- package java.lang.Object is
- -- type Typ is tagged limited private;
- -- type Ref is access all Typ'Class;
- -- private
- -- type Typ is tagged limited ...;
- -- pragma Convention (Typ, Java)
- -- end;
+ -- package java.lang.Object is
+ -- type Typ is tagged limited private;
+ -- type Ref is access all Typ'Class;
+ -- private
+ -- type Typ is tagged limited ...;
+ -- pragma Convention (Typ, Java)
+ -- end;
- -- Because the convention appears after we have done the
- -- processing for type Ref.
+ -- Because the convention appears after we have done the
+ -- processing for type Ref.
- and then Convention (Designated_Type (Def_Id)) /= Convention_Java
- and then Convention (Designated_Type (Def_Id)) /= Convention_CIL
+ and then Convention (Desig_Typ) /= Convention_Java
+ and then Convention (Desig_Typ) /= Convention_CIL
then
- Build_Class_Wide_Master (Def_Id);
+ Build_Class_Wide_Master (Ptr_Typ);
end if;
end Build_Master;
+ -- Local declarations
+
+ Def_Id : constant Entity_Id := Defining_Identifier (N);
+ B_Id : constant Entity_Id := Base_Type (Def_Id);
+ FN : Node_Id;
+ Par_Id : Entity_Id;
+
-- Start of processing for Expand_N_Full_Type_Declaration
begin
@@ -4390,6 +4195,8 @@ package body Exp_Ch3 is
Expand_Access_Protected_Subprogram_Type (N);
end if;
+ -- Array of anonymous access-to-task pointers
+
elsif Ada_Version >= Ada_2005
and then Is_Array_Type (Def_Id)
and then Is_Access_Type (Component_Type (Def_Id))
@@ -4400,73 +4207,57 @@ package body Exp_Ch3 is
elsif Has_Task (Def_Id) then
Expand_Previous_Access_Type (Def_Id);
+ -- Check the components of a record type or array of records for
+ -- anonymous access-to-task pointers.
+
elsif Ada_Version >= Ada_2005
- and then
- (Is_Record_Type (Def_Id)
- or else (Is_Array_Type (Def_Id)
- and then Is_Record_Type (Component_Type (Def_Id))))
+ and then (Is_Record_Type (Def_Id)
+ or else
+ (Is_Array_Type (Def_Id)
+ and then Is_Record_Type (Component_Type (Def_Id))))
then
declare
- Comp : Entity_Id;
- Typ : Entity_Id;
- M_Id : Entity_Id;
+ Comp : Entity_Id;
+ First : Boolean;
+ M_Id : Entity_Id;
+ Typ : Entity_Id;
begin
- -- Look for the first anonymous access type component
-
if Is_Array_Type (Def_Id) then
Comp := First_Entity (Component_Type (Def_Id));
else
Comp := First_Entity (Def_Id);
end if;
+ -- Examine all components looking for anonymous access-to-task
+ -- types.
+
+ First := True;
while Present (Comp) loop
Typ := Etype (Comp);
- exit when Is_Access_Type (Typ)
- and then Ekind (Typ) = E_Anonymous_Access_Type;
-
- Next_Entity (Comp);
- end loop;
-
- -- If found we add a renaming declaration of master_id and we
- -- associate it to each anonymous access type component. Do
- -- nothing if the access type already has a master. This will be
- -- the case if the array type is the packed array created for a
- -- user-defined array type T, where the master_id is created when
- -- expanding the declaration for T.
-
- if Present (Comp)
- and then Ekind (Typ) = E_Anonymous_Access_Type
- and then not Restriction_Active (No_Task_Hierarchy)
- and then No (Master_Id (Typ))
-
- -- Do not consider run-times with no tasking support
+ if Ekind (Typ) = E_Anonymous_Access_Type
+ and then Has_Task (Available_View (Designated_Type (Typ)))
+ and then No (Master_Id (Typ))
+ then
+ -- Ensure that the record or array type have a _master
- and then RTE_Available (RE_Current_Master)
- and then Has_Task (Non_Limited_Designated_Type (Typ))
- then
- Build_Master_Entity (Def_Id);
- M_Id := Build_Master_Renaming (N, Def_Id);
+ if First then
+ Build_Master_Entity (Def_Id);
+ Build_Master_Renaming (Typ);
+ M_Id := Master_Id (Typ);
- if Is_Array_Type (Def_Id) then
- Comp := First_Entity (Component_Type (Def_Id));
- else
- Comp := First_Entity (Def_Id);
- end if;
+ First := False;
- while Present (Comp) loop
- Typ := Etype (Comp);
+ -- Reuse the same master to service any additional types
- if Is_Access_Type (Typ)
- and then Ekind (Typ) = E_Anonymous_Access_Type
- then
+ else
Set_Master_Id (Typ, M_Id);
end if;
+ end if;
- Next_Entity (Comp);
- end loop;
- end if;
+ Next_Entity (Comp);
+ end loop;
end;
end if;
@@ -4482,7 +4273,7 @@ package body Exp_Ch3 is
end if;
if Nkind (Type_Definition (Original_Node (N))) =
- N_Derived_Type_Definition
+ N_Derived_Type_Definition
and then not Is_Tagged_Type (Def_Id)
and then Present (Freeze_Node (Par_Id))
and then Present (TSS_Elist (Freeze_Node (Par_Id)))
@@ -5387,23 +5178,31 @@ package body Exp_Ch3 is
---------------------------------
procedure Expand_Previous_Access_Type (Def_Id : Entity_Id) is
- T : Entity_Id := First_Entity (Current_Scope);
+ Ptr_Typ : Entity_Id;
begin
- -- Find all access types declared in the current scope, whose
- -- designated type is Def_Id. If it does not have a Master_Id,
- -- create one now.
-
- while Present (T) loop
- if Is_Access_Type (T)
- and then Designated_Type (T) = Def_Id
- and then No (Master_Id (T))
+ -- Find all access types in the current scope whose designated type is
+ -- Def_Id and build master renamings for them.
+
+ Ptr_Typ := First_Entity (Current_Scope);
+ while Present (Ptr_Typ) loop
+ if Is_Access_Type (Ptr_Typ)
+ and then Designated_Type (Ptr_Typ) = Def_Id
+ and then No (Master_Id (Ptr_Typ))
then
+ -- Ensure that the designated type has a master
+
Build_Master_Entity (Def_Id);
- Build_Master_Renaming (Parent (Def_Id), T);
+
+ -- Private and incomplete types complicate the insertion of master
+ -- renamings because the access type may precede the full view of
+ -- the designated type. For this reason, the master renamings are
+ -- inserted relative to the designated type.
+
+ Build_Master_Renaming (Ptr_Typ, Ins_Nod => Parent (Def_Id));
end if;
- Next_Entity (T);
+ Next_Entity (Ptr_Typ);
end loop;
end Expand_Previous_Access_Type;
@@ -6289,7 +6088,7 @@ package body Exp_Ch3 is
end if;
end if;
- -- In the non-tagged case, ever since Ada83 an equality function must
+ -- In the non-tagged case, ever since Ada 83 an equality function must
-- be provided for variant records that are not unchecked unions.
-- In Ada 2012 the equality function composes, and thus must be built
-- explicitly just as for tagged records.
diff --git a/gcc/ada/exp_ch3.ads b/gcc/ada/exp_ch3.ads
index 7b67e23a8cf..8cedc0b05cd 100644
--- a/gcc/ada/exp_ch3.ads
+++ b/gcc/ada/exp_ch3.ads
@@ -46,15 +46,6 @@ package Exp_Ch3 is
procedure Expand_Record_Extension (T : Entity_Id; Def : Node_Id);
-- Add a field _parent in the extension part of the record
- procedure Build_Class_Wide_Master (T : Entity_Id);
- -- For access to class-wide limited types we must build a task master
- -- because some subsequent extension may add a task component. To avoid
- -- bringing in the tasking run-time whenever an access-to-class-wide
- -- limited type is used, we use the soft-link mechanism and add a level of
- -- indirection to calls to routines that manipulate Master_Ids. This must
- -- also be used for anonymous access types whose designated type is a task
- -- or synchronized interface.
-
procedure Build_Discr_Checking_Funcs (N : Node_Id);
-- Builds function which checks whether the component name is consistent
-- with the current discriminants. N is the full type declaration node,
@@ -93,19 +84,6 @@ package Exp_Ch3 is
-- Constructor_Ref is a call to a constructor subprogram. It is currently
-- used only to support C++ constructors.
- procedure Build_Master_Renaming (N : Node_Id; T : Entity_Id);
- -- If the designated type of an access type is a task type or contains
- -- tasks, we make sure that a _Master variable is declared in the current
- -- scope, and then declare a renaming for it:
- --
- -- atypeM : Master_Id renames _Master;
- --
- -- where atyp is the name of the access type. This declaration is
- -- used when an allocator for the access type is expanded. The node N
- -- is the full declaration of the designated type that contains tasks.
- -- The renaming declaration is inserted before N, and after the Master
- -- declaration.
-
function Freeze_Type (N : Node_Id) return Boolean;
-- This function executes the freezing actions associated with the given
-- freeze type node N and returns True if the node is to be deleted. We
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index c099933c310..87e02d0e1ee 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -765,7 +765,7 @@ package body Exp_Ch4 is
-- Start of processing for Expand_Allocator_Expression
begin
- -- In the case of an Ada2012 allocator whose initial value comes from a
+ -- In the case of an Ada 2012 allocator whose initial value comes from a
-- function call, pass "the accessibility level determined by the point
-- of call" (AI05-0234) to the function. Conceptually, this belongs in
-- Expand_Call but it couldn't be done there (because the Etype of the
@@ -3526,23 +3526,28 @@ package body Exp_Ch4 is
end if;
-- Set the storage pool and find the appropriate version of Allocate to
- -- call.
+ -- call. Do not overwrite the storage pool if it is already set, which
+ -- can happen for build-in-place function returns (see
+ -- Exp_Ch4.Expand_N_Extended_Return_Statement).
- Pool := Associated_Storage_Pool (Root_Type (PtrT));
- Set_Storage_Pool (N, Pool);
+ if No (Storage_Pool (N)) then
+ Pool := Associated_Storage_Pool (Root_Type (PtrT));
- if Present (Pool) then
- if Is_RTE (Pool, RE_SS_Pool) then
- if VM_Target = No_VM then
- Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
- end if;
+ if Present (Pool) then
+ Set_Storage_Pool (N, Pool);
- elsif Is_Class_Wide_Type (Etype (Pool)) then
- Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
+ if Is_RTE (Pool, RE_SS_Pool) then
+ if VM_Target = No_VM then
+ Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
+ end if;
- else
- Set_Procedure_To_Call (N,
- Find_Prim_Op (Etype (Pool), Name_Allocate));
+ elsif Is_Class_Wide_Type (Etype (Pool)) then
+ Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
+
+ else
+ Set_Procedure_To_Call (N,
+ Find_Prim_Op (Etype (Pool), Name_Allocate));
+ end if;
end if;
end if;
@@ -5574,26 +5579,10 @@ package body Exp_Ch4 is
Expand_Boolean_Operator (N);
elsif Is_Boolean_Type (Etype (N)) then
-
- -- Replace AND by AND THEN if Short_Circuit_And_Or active and the
- -- type is standard Boolean (do not mess with AND that uses a non-
- -- standard Boolean type, because something strange is going on).
-
- if Short_Circuit_And_Or and then Typ = Standard_Boolean then
- Rewrite (N,
- Make_And_Then (Sloc (N),
- Left_Opnd => Relocate_Node (Left_Opnd (N)),
- Right_Opnd => Relocate_Node (Right_Opnd (N))));
- Analyze_And_Resolve (N, Typ);
-
- -- Otherwise, adjust conditions
-
- else
- Adjust_Condition (Left_Opnd (N));
- Adjust_Condition (Right_Opnd (N));
- Set_Etype (N, Standard_Boolean);
- Adjust_Result_Type (N, Typ);
- end if;
+ Adjust_Condition (Left_Opnd (N));
+ Adjust_Condition (Right_Opnd (N));
+ Set_Etype (N, Standard_Boolean);
+ Adjust_Result_Type (N, Typ);
elsif Is_Intrinsic_Subprogram (Entity (N)) then
Expand_Intrinsic_Call (N, Entity (N));
@@ -7530,26 +7519,10 @@ package body Exp_Ch4 is
Expand_Boolean_Operator (N);
elsif Is_Boolean_Type (Etype (N)) then
-
- -- Replace OR by OR ELSE if Short_Circuit_And_Or active and the type
- -- is standard Boolean (do not mess with AND that uses a non-standard
- -- Boolean type, because something strange is going on).
-
- if Short_Circuit_And_Or and then Typ = Standard_Boolean then
- Rewrite (N,
- Make_Or_Else (Sloc (N),
- Left_Opnd => Relocate_Node (Left_Opnd (N)),
- Right_Opnd => Relocate_Node (Right_Opnd (N))));
- Analyze_And_Resolve (N, Typ);
-
- -- Otherwise, adjust conditions
-
- else
- Adjust_Condition (Left_Opnd (N));
- Adjust_Condition (Right_Opnd (N));
- Set_Etype (N, Standard_Boolean);
- Adjust_Result_Type (N, Typ);
- end if;
+ Adjust_Condition (Left_Opnd (N));
+ Adjust_Condition (Right_Opnd (N));
+ Set_Etype (N, Standard_Boolean);
+ Adjust_Result_Type (N, Typ);
elsif Is_Intrinsic_Subprogram (Entity (N)) then
Expand_Intrinsic_Call (N, Entity (N));
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index 291d68e7b3e..8d487727009 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -3458,6 +3458,20 @@ package body Exp_Ch5 is
Statements => Statements (N)))),
End_Label => End_Label (N)));
+
+ -- The loop parameter's entity must be removed from the loop
+ -- scope's entity list, since itw will now be located in the
+ -- new block scope. Any other entities already associated with
+ -- the loop scope, such as the loop parameter's subtype, will
+ -- remain there.
+
+ pragma Assert (First_Entity (Scope (Loop_Id)) = Loop_Id);
+ Set_First_Entity (Scope (Loop_Id), Next_Entity (Loop_Id));
+
+ if Last_Entity (Scope (Loop_Id)) = Loop_Id then
+ Set_Last_Entity (Scope (Loop_Id), Empty);
+ end if;
+
Analyze (N);
-- Nothing to do with other cases of for loops
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 8955e5d9174..993fa40c3fa 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -94,15 +94,18 @@ package body Exp_Ch6 is
-- along directly to the build-in-place function. Finally, if Return_Object
-- is empty, then pass a null literal as the actual.
- procedure Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ procedure Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Function_Call : Node_Id;
Function_Id : Entity_Id;
Alloc_Form : BIP_Allocation_Form := Unspecified;
- Alloc_Form_Exp : Node_Id := Empty);
- -- Ada 2005 (AI-318-02): Add an actual indicating the form of allocation,
- -- if any, to be done by a build-in-place function. If Alloc_Form_Exp is
- -- present, then use it, otherwise pass a literal corresponding to the
- -- Alloc_Form parameter (which must not be Unspecified in that case).
+ Alloc_Form_Exp : Node_Id := Empty;
+ Pool_Actual : Node_Id := Make_Null (No_Location));
+ -- Ada 2005 (AI-318-02): Add the actuals needed for a build-in-place
+ -- function call that returns a caller-unknown-size result (BIP_Alloc_Form
+ -- and BIP_Storage_Pool). If Alloc_Form_Exp is present, then use it,
+ -- otherwise pass a literal corresponding to the Alloc_Form parameter
+ -- (which must not be Unspecified in that case). Pool_Actual is the
+ -- parameter to pass to BIP_Storage_Pool.
procedure Add_Finalization_Master_Actual_To_Build_In_Place_Call
(Func_Call : Node_Id;
@@ -251,19 +254,21 @@ package body Exp_Ch6 is
Add_Extra_Actual_To_Call (Function_Call, Obj_Acc_Formal, Obj_Address);
end Add_Access_Actual_To_Build_In_Place_Call;
- --------------------------------------------------
- -- Add_Alloc_Form_Actual_To_Build_In_Place_Call --
- --------------------------------------------------
+ ------------------------------------------------------
+ -- Add_Unconstrained_Actuals_To_Build_In_Place_Call --
+ ------------------------------------------------------
- procedure Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ procedure Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Function_Call : Node_Id;
Function_Id : Entity_Id;
Alloc_Form : BIP_Allocation_Form := Unspecified;
- Alloc_Form_Exp : Node_Id := Empty)
+ Alloc_Form_Exp : Node_Id := Empty;
+ Pool_Actual : Node_Id := Make_Null (No_Location))
is
Loc : constant Source_Ptr := Sloc (Function_Call);
Alloc_Form_Actual : Node_Id;
Alloc_Form_Formal : Node_Id;
+ Pool_Formal : Node_Id;
begin
-- The allocation form generally doesn't need to be passed in the case
@@ -305,7 +310,19 @@ package body Exp_Ch6 is
Add_Extra_Actual_To_Call
(Function_Call, Alloc_Form_Formal, Alloc_Form_Actual);
- end Add_Alloc_Form_Actual_To_Build_In_Place_Call;
+
+ -- Pass the Storage_Pool parameter. This parameter is omitted on
+ -- .NET/JVM/ZFP as those targets do not support pools.
+
+ if VM_Target = No_VM
+ and then RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Pool_Formal := Build_In_Place_Formal (Function_Id, BIP_Storage_Pool);
+ Analyze_And_Resolve (Pool_Actual, Etype (Pool_Formal));
+ Add_Extra_Actual_To_Call
+ (Function_Call, Pool_Formal, Pool_Actual);
+ end if;
+ end Add_Unconstrained_Actuals_To_Build_In_Place_Call;
-----------------------------------------------------------
-- Add_Finalization_Master_Actual_To_Build_In_Place_Call --
@@ -462,16 +479,23 @@ package body Exp_Ch6 is
Function_Id : Entity_Id;
Master_Actual : Node_Id)
is
- Loc : constant Source_Ptr := Sloc (Function_Call);
- Actual : Node_Id := Master_Actual;
+ Loc : constant Source_Ptr := Sloc (Function_Call);
+ Result_Subt : constant Entity_Id :=
+ Available_View (Etype (Function_Id));
+ Actual : Node_Id;
+ Chain_Actual : Node_Id;
+ Chain_Formal : Node_Id;
+ Master_Formal : Node_Id;
begin
-- No such extra parameters are needed if there are no tasks
- if not Has_Task (Available_View (Etype (Function_Id))) then
+ if not Has_Task (Result_Subt) then
return;
end if;
+ Actual := Master_Actual;
+
-- Use a dummy _master actual in case of No_Task_Hierarchy
if Restriction_Active (No_Task_Hierarchy) then
@@ -484,52 +508,34 @@ package body Exp_Ch6 is
Actual := New_Reference_To (Actual, Loc);
end if;
- -- The master
-
- declare
- Master_Formal : Node_Id;
- begin
- -- Locate implicit master parameter in the called function
-
- Master_Formal := Build_In_Place_Formal (Function_Id, BIP_Master);
+ -- Locate the implicit master parameter in the called function
- Analyze_And_Resolve (Actual, Etype (Master_Formal));
+ Master_Formal := Build_In_Place_Formal (Function_Id, BIP_Task_Master);
+ Analyze_And_Resolve (Actual, Etype (Master_Formal));
- -- Build the parameter association for the new actual and add it to
- -- the end of the function's actuals.
+ -- Build the parameter association for the new actual and add it to the
+ -- end of the function's actuals.
- Add_Extra_Actual_To_Call (Function_Call, Master_Formal, Actual);
- end;
+ Add_Extra_Actual_To_Call (Function_Call, Master_Formal, Actual);
- -- The activation chain
+ -- Locate the implicit activation chain parameter in the called function
- declare
- Activation_Chain_Actual : Node_Id;
- Activation_Chain_Formal : Node_Id;
+ Chain_Formal :=
+ Build_In_Place_Formal (Function_Id, BIP_Activation_Chain);
- begin
- -- Locate implicit activation chain parameter in the called function
+ -- Create the actual which is a pointer to the current activation chain
- Activation_Chain_Formal :=
- Build_In_Place_Formal (Function_Id, BIP_Activation_Chain);
+ Chain_Actual :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Make_Identifier (Loc, Name_uChain),
+ Attribute_Name => Name_Unrestricted_Access);
- -- Create the actual which is a pointer to the current activation
- -- chain
+ Analyze_And_Resolve (Chain_Actual, Etype (Chain_Formal));
- Activation_Chain_Actual :=
- Make_Attribute_Reference (Loc,
- Prefix => Make_Identifier (Loc, Name_uChain),
- Attribute_Name => Name_Unrestricted_Access);
-
- Analyze_And_Resolve
- (Activation_Chain_Actual, Etype (Activation_Chain_Formal));
-
- -- Build the parameter association for the new actual and add it to
- -- the end of the function's actuals.
+ -- Build the parameter association for the new actual and add it to the
+ -- end of the function's actuals.
- Add_Extra_Actual_To_Call
- (Function_Call, Activation_Chain_Formal, Activation_Chain_Actual);
- end;
+ Add_Extra_Actual_To_Call (Function_Call, Chain_Formal, Chain_Actual);
end Add_Task_Actuals_To_Build_In_Place_Call;
-----------------------
@@ -541,10 +547,12 @@ package body Exp_Ch6 is
case Kind is
when BIP_Alloc_Form =>
return "BIPalloc";
+ when BIP_Storage_Pool =>
+ return "BIPstoragepool";
when BIP_Finalization_Master =>
return "BIPfinalizationmaster";
- when BIP_Master =>
- return "BIPmaster";
+ when BIP_Task_Master =>
+ return "BIPtaskmaster";
when BIP_Activation_Chain =>
return "BIPactivationchain";
when BIP_Object_Access =>
@@ -560,6 +568,9 @@ package body Exp_Ch6 is
(Func : Entity_Id;
Kind : BIP_Formal_Kind) return Entity_Id
is
+ Formal_Name : constant Name_Id :=
+ New_External_Name
+ (Chars (Func), BIP_Formal_Suffix (Kind));
Extra_Formal : Entity_Id := Extra_Formals (Func);
begin
@@ -578,9 +589,8 @@ package body Exp_Ch6 is
loop
pragma Assert (Present (Extra_Formal));
- exit when
- Chars (Extra_Formal) =
- New_External_Name (Chars (Func), BIP_Formal_Suffix (Kind));
+ exit when Chars (Extra_Formal) = Formal_Name;
+
Next_Formal_With_Extras (Extra_Formal);
end loop;
@@ -4573,6 +4583,7 @@ package body Exp_Ch6 is
Par_Func : constant Entity_Id :=
Return_Applies_To (Return_Statement_Entity (N));
+ Result_Subt : constant Entity_Id := Etype (Par_Func);
Ret_Obj_Id : constant Entity_Id :=
First_Entity (Return_Statement_Entity (N));
Ret_Obj_Decl : constant Node_Id := Parent (Ret_Obj_Id);
@@ -4638,11 +4649,12 @@ package body Exp_Ch6 is
Alloc_Expr : Node_Id) return Node_Id
is
begin
+ pragma Assert (Is_Build_In_Place_Function (Func_Id));
+
-- Processing for build-in-place object allocation. This is disabled
-- on .NET/JVM because the targets do not support pools.
if VM_Target = No_VM
- and then Is_Build_In_Place_Function (Func_Id)
and then Needs_Finalization (Ret_Typ)
then
declare
@@ -4811,7 +4823,7 @@ package body Exp_Ch6 is
-- New master
New_Reference_To
- (Build_In_Place_Formal (Par_Func, BIP_Master), Loc)));
+ (Build_In_Place_Formal (Par_Func, BIP_Task_Master), Loc)));
end Move_Activation_Chain;
-- Start of processing for Expand_N_Extended_Return_Statement
@@ -4876,7 +4888,7 @@ package body Exp_Ch6 is
-- built in place (though we plan to do so eventually).
if Present (HSS)
- or else Is_Composite_Type (Etype (Par_Func))
+ or else Is_Composite_Type (Result_Subt)
or else No (Exp)
then
if No (HSS) then
@@ -4903,7 +4915,7 @@ package body Exp_Ch6 is
-- the case of result types with task parts.
if Is_Build_In_Place
- and then Has_Task (Etype (Par_Func))
+ and then Has_Task (Result_Subt)
then
-- The return expression is an aggregate for a complex type which
-- contains tasks. This particular case is left unexpanded since
@@ -4914,7 +4926,12 @@ package body Exp_Ch6 is
Expand_N_Aggregate (Exp);
end if;
- Append_To (Stmts, Move_Activation_Chain);
+ -- Do not move the activation chain if the return object does not
+ -- contain tasks.
+
+ if Has_Task (Etype (Ret_Obj_Id)) then
+ Append_To (Stmts, Move_Activation_Chain);
+ end if;
end if;
-- Update the state of the function right before the object is
@@ -5013,7 +5030,6 @@ package body Exp_Ch6 is
Return_Obj_Typ : constant Entity_Id := Etype (Return_Obj_Id);
Return_Obj_Expr : constant Node_Id :=
Expression (Ret_Obj_Decl);
- Result_Subt : constant Entity_Id := Etype (Par_Func);
Constr_Result : constant Boolean :=
Is_Constrained (Result_Subt);
Obj_Alloc_Formal : Entity_Id;
@@ -5116,12 +5132,16 @@ package body Exp_Ch6 is
Build_In_Place_Formal (Par_Func, BIP_Alloc_Form);
declare
- Ref_Type : Entity_Id;
- Ptr_Type_Decl : Node_Id;
+ Pool_Id : constant Entity_Id :=
+ Make_Temporary (Loc, 'P');
Alloc_Obj_Id : Entity_Id;
Alloc_Obj_Decl : Node_Id;
Alloc_If_Stmt : Node_Id;
Heap_Allocator : Node_Id;
+ Pool_Decl : Node_Id;
+ Pool_Allocator : Node_Id;
+ Ptr_Type_Decl : Node_Id;
+ Ref_Type : Entity_Id;
SS_Allocator : Node_Id;
begin
@@ -5216,6 +5236,37 @@ package body Exp_Ch6 is
Set_No_Initialization (Heap_Allocator);
end if;
+ -- The Pool_Allocator is just like the Heap_Allocator,
+ -- except we set Storage_Pool and Procedure_To_Call so
+ -- it will use the user-defined storage pool.
+
+ Pool_Allocator := New_Copy_Tree (Heap_Allocator);
+
+ -- Do not generate the renaming of the build-in-place
+ -- pool parameter on .NET/JVM/ZFP because the parameter
+ -- is not created in the first place.
+
+ if VM_Target = No_VM
+ and then RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Pool_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Pool_Id,
+ Subtype_Mark =>
+ New_Reference_To
+ (RTE (RE_Root_Storage_Pool), Loc),
+ Name =>
+ Make_Explicit_Dereference (Loc,
+ New_Reference_To
+ (Build_In_Place_Formal
+ (Par_Func, BIP_Storage_Pool), Loc)));
+ Set_Storage_Pool (Pool_Allocator, Pool_Id);
+ Set_Procedure_To_Call
+ (Pool_Allocator, RTE (RE_Allocate_Any));
+ else
+ Pool_Decl := Make_Null_Statement (Loc);
+ end if;
+
-- If the No_Allocators restriction is active, then only
-- an allocator for secondary stack allocation is needed.
-- It's OK for such allocators to have Comes_From_Source
@@ -5225,22 +5276,25 @@ package body Exp_Ch6 is
if Restriction_Active (No_Allocators) then
SS_Allocator := Heap_Allocator;
Heap_Allocator := Make_Null (Loc);
+ Pool_Allocator := Make_Null (Loc);
- -- Otherwise the heap allocator may be needed, so we make
- -- another allocator for secondary stack allocation.
+ -- Otherwise the heap and pool allocators may be needed,
+ -- so we make another allocator for secondary stack
+ -- allocation.
else
SS_Allocator := New_Copy_Tree (Heap_Allocator);
- -- The heap allocator is marked Comes_From_Source
- -- since it corresponds to an explicit user-written
- -- allocator (that is, it will only be executed on
- -- behalf of callers that call the function as
- -- initialization for such an allocator). This
- -- prevents errors when No_Implicit_Heap_Allocations
+ -- The heap and pool allocators are marked as
+ -- Comes_From_Source since they correspond to an
+ -- explicit user-written allocator (that is, it will
+ -- only be executed on behalf of callers that call the
+ -- function as initialization for such an allocator).
+ -- Prevents errors when No_Implicit_Heap_Allocations
-- is in force.
Set_Comes_From_Source (Heap_Allocator, True);
+ Set_Comes_From_Source (Pool_Allocator, True);
end if;
-- The allocator is returned on the secondary stack. We
@@ -5269,10 +5323,12 @@ package body Exp_Ch6 is
-- Create an if statement to test the BIP_Alloc_Form
-- formal and initialize the access object to either the
- -- BIP_Object_Access formal (BIP_Alloc_Form = 0), the
- -- result of allocating the object in the secondary stack
- -- (BIP_Alloc_Form = 1), or else an allocator to create
- -- the return object in the heap (BIP_Alloc_Form = 2).
+ -- BIP_Object_Access formal (BIP_Alloc_Form =
+ -- Caller_Allocation), the result of allocating the
+ -- object in the secondary stack (BIP_Alloc_Form =
+ -- Secondary_Stack), or else an allocator to create the
+ -- return object in the heap or user-defined pool
+ -- (BIP_Alloc_Form = Global_Heap or User_Storage_Pool).
-- ??? An unchecked type conversion must be made in the
-- case of assigning the access object formal to the
@@ -5320,15 +5376,34 @@ package body Exp_Ch6 is
Make_Assignment_Statement (Loc,
Name =>
New_Reference_To (Alloc_Obj_Id, Loc),
- Expression => SS_Allocator)))),
+ Expression => SS_Allocator))),
+
+ Make_Elsif_Part (Loc,
+ Condition =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ New_Reference_To (Obj_Alloc_Formal, Loc),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc,
+ UI_From_Int (BIP_Allocation_Form'Pos
+ (Global_Heap)))),
+
+ Then_Statements => New_List (
+ Build_Heap_Allocator
+ (Temp_Id => Alloc_Obj_Id,
+ Temp_Typ => Ref_Type,
+ Func_Id => Par_Func,
+ Ret_Typ => Return_Obj_Typ,
+ Alloc_Expr => Heap_Allocator)))),
Else_Statements => New_List (
+ Pool_Decl,
Build_Heap_Allocator
(Temp_Id => Alloc_Obj_Id,
Temp_Typ => Ref_Type,
Func_Id => Par_Func,
Ret_Typ => Return_Obj_Typ,
- Alloc_Expr => Heap_Allocator)));
+ Alloc_Expr => Pool_Allocator)));
-- If a separate initialization assignment was created
-- earlier, append that following the assignment of the
@@ -7592,7 +7667,7 @@ package body Exp_Ch6 is
-- called as a dispatching operation and must be treated similarly
-- to functions with unconstrained result subtypes.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7623,11 +7698,30 @@ package body Exp_Ch6 is
-- operations. ???
else
- -- Pass an allocation parameter indicating that the function should
- -- allocate its result on the heap.
+ -- Case of a user-defined storage pool. Pass an allocation parameter
+ -- indicating that the function should allocate its result in the
+ -- pool, and pass the pool. Use 'Unrestricted_Access because the
+ -- pool may not be aliased.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
- (Func_Call, Function_Id, Alloc_Form => Global_Heap);
+ if VM_Target = No_VM
+ and then Present (Associated_Storage_Pool (Acc_Type))
+ then
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
+ (Func_Call, Function_Id, Alloc_Form => User_Storage_Pool,
+ Pool_Actual =>
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Reference_To
+ (Associated_Storage_Pool (Acc_Type), Loc),
+ Attribute_Name => Name_Unrestricted_Access));
+
+ -- No user-defined pool; pass an allocation parameter indicating that
+ -- the function should allocate its result on the heap.
+
+ else
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
+ (Func_Call, Function_Id, Alloc_Form => Global_Heap);
+ end if;
Add_Finalization_Master_Actual_To_Build_In_Place_Call
(Func_Call, Function_Id, Acc_Type);
@@ -7796,7 +7890,7 @@ package body Exp_Ch6 is
-- called as a dispatching operation and must be treated similarly
-- to functions with unconstrained result subtypes.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7820,7 +7914,7 @@ package body Exp_Ch6 is
-- Pass an allocation parameter indicating that the function should
-- allocate its result on the secondary stack.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Secondary_Stack);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7898,7 +7992,7 @@ package body Exp_Ch6 is
-- controlling result, because dispatching calls to the function needs
-- to be treated effectively the same as calls to class-wide functions.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Func_Id, Alloc_Form => Caller_Allocation);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7978,20 +8072,20 @@ package body Exp_Ch6 is
Loc : Source_Ptr;
Obj_Def_Id : constant Entity_Id :=
Defining_Identifier (Object_Decl);
-
- Func_Call : Node_Id := Function_Call;
- Function_Id : Entity_Id;
- Result_Subt : Entity_Id;
- Caller_Object : Node_Id;
- Call_Deref : Node_Id;
- Ref_Type : Entity_Id;
- Ptr_Typ_Decl : Node_Id;
- Def_Id : Entity_Id;
- New_Expr : Node_Id;
Enclosing_Func : constant Entity_Id :=
Enclosing_Subprogram (Obj_Def_Id);
+ Call_Deref : Node_Id;
+ Caller_Object : Node_Id;
+ Def_Id : Entity_Id;
Fmaster_Actual : Node_Id := Empty;
+ Func_Call : Node_Id := Function_Call;
+ Function_Id : Entity_Id;
+ Pool_Actual : Node_Id;
+ Ptr_Typ_Decl : Node_Id;
Pass_Caller_Acc : Boolean := False;
+ New_Expr : Node_Id;
+ Ref_Type : Entity_Id;
+ Result_Subt : Entity_Id;
begin
-- Step past qualification or unchecked conversion (the latter can occur
@@ -8047,19 +8141,33 @@ package body Exp_Ch6 is
-- has an unconstrained or tagged result type).
if Needs_BIP_Alloc_Form (Enclosing_Func) then
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ if VM_Target = No_VM and then
+ RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Pool_Actual :=
+ New_Reference_To (Build_In_Place_Formal
+ (Enclosing_Func, BIP_Storage_Pool), Loc);
+
+ -- The build-in-place pool formal is not built on .NET/JVM
+
+ else
+ Pool_Actual := Empty;
+ end if;
+
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call,
Function_Id,
Alloc_Form_Exp =>
New_Reference_To
(Build_In_Place_Formal (Enclosing_Func, BIP_Alloc_Form),
- Loc));
+ Loc),
+ Pool_Actual => Pool_Actual);
-- Otherwise, if enclosing function has a constrained result subtype,
-- then caller allocation will be used.
else
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
end if;
@@ -8102,7 +8210,7 @@ package body Exp_Ch6 is
-- called as a dispatching operation and must be treated similarly
-- to functions with unconstrained result subtypes.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
-- In other unconstrained cases, pass an indication to do the allocation
@@ -8111,10 +8219,8 @@ package body Exp_Ch6 is
-- scope is established to ensure eventual cleanup of the result.
else
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
- (Func_Call,
- Function_Id,
- Alloc_Form => Secondary_Stack);
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
+ (Func_Call, Function_Id, Alloc_Form => Secondary_Stack);
Caller_Object := Empty;
Establish_Transient_Scope (Object_Decl, Sec_Stack => True);
@@ -8138,8 +8244,8 @@ package body Exp_Ch6 is
Add_Task_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id,
Master_Actual =>
- New_Reference_To
- (Build_In_Place_Formal (Enclosing_Func, BIP_Master), Loc));
+ New_Reference_To (Build_In_Place_Formal
+ (Enclosing_Func, BIP_Task_Master), Loc));
else
Add_Task_Actuals_To_Build_In_Place_Call
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index 06145f525e0..77df2b7da42 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -88,21 +88,26 @@ package Exp_Ch6 is
type BIP_Formal_Kind is
-- Ada 2005 (AI-318-02): This type defines the kinds of implicit extra
- -- formals created for build-in-place functions. The order of the above
+ -- formals created for build-in-place functions. The order of these
-- enumeration literals matches the order in which the formals are
-- declared. See Sem_Ch6.Create_Extra_Formals.
(BIP_Alloc_Form,
- -- Present if result subtype is unconstrained, or if the result type
- -- is tagged. Indicates whether the return object is allocated by the
- -- caller or callee, and if the callee, whether to use the secondary
- -- stack or the heap. See Create_Extra_Formals.
+ -- Present if result subtype is unconstrained or tagged. Indicates
+ -- whether the return object is allocated by the caller or callee, and
+ -- if the callee, whether to use the secondary stack or the heap. See
+ -- Create_Extra_Formals.
+
+ BIP_Storage_Pool,
+ -- Present if result subtype is unconstrained or tagged. If
+ -- BIP_Alloc_Form = User_Storage_Pool, this is a pointer to the pool
+ -- (of type access to Root_Storage_Pool'Class). Otherwise null.
BIP_Finalization_Master,
-- Present if result type needs finalization. Pointer to caller's
-- finalization master.
- BIP_Master,
+ BIP_Task_Master,
-- Present if result type contains tasks. Master associated with
-- calling context.
@@ -114,8 +119,7 @@ package Exp_Ch6 is
-- the return object, or null if BIP_Alloc_Form indicates allocated by
-- callee.
--
- -- ??? We also need to be able to pass in some way to access a user-
- -- defined storage pool at some point. And perhaps a constrained flag.
+ -- ??? We might also need to be able to pass in a constrained flag.
function BIP_Formal_Suffix (Kind : BIP_Formal_Kind) return String;
-- Ada 2005 (AI-318-02): Returns a string to be used as the suffix of names
@@ -197,14 +201,14 @@ package Exp_Ch6 is
-- for which Is_Build_In_Place_Call is True, or an N_Qualified_Expression
-- node applied to such a function call.
- function Needs_BIP_Finalization_Master (Func_Id : Entity_Id) return Boolean;
- -- Ada 2005 (AI-318-02): Return True if the function needs an implicit
- -- finalization master implicit parameter.
-
function Needs_BIP_Alloc_Form (Func_Id : Entity_Id) return Boolean;
-- Ada 2005 (AI-318-02): Return True if the function needs an implicit
-- BIP_Alloc_Form parameter (see type BIP_Formal_Kind).
+ function Needs_BIP_Finalization_Master (Func_Id : Entity_Id) return Boolean;
+ -- Ada 2005 (AI-318-02): Return True if the result subtype of function
+ -- Func_Id needs finalization actions.
+
function Needs_Result_Accessibility_Level
(Func_Id : Entity_Id) return Boolean;
-- Ada 2012 (AI05-0234): Return True if the function needs an implicit
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index c7ea703d272..27b1cd764e0 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -3842,7 +3842,7 @@ package body Exp_Ch7 is
----------------------------------
-- Add call to Activate_Tasks if there are tasks declared and the package
- -- has no body. Note that in Ada83, this may result in premature activation
+ -- has no body. Note that in Ada 83 this may result in premature activation
-- of some tasks, given that we cannot tell whether a body will eventually
-- appear.
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index fc70238aedb..8305278e8d8 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -178,7 +178,7 @@ package body Exp_Ch9 is
-- body or an accept body. The renamed object is a component of the
-- parameter block that is a parameter in the entry call.
- -- In Ada2012, If the formal is an incomplete tagged type, the renaming
+ -- In Ada 2012, if the formal is an incomplete tagged type, the renaming
-- does not dereference the corresponding component to prevent an illegal
-- use of the incomplete type (AI05-0151).
@@ -346,6 +346,18 @@ package body Exp_Ch9 is
-- to handle properly the case of bounds that depend on discriminants.
-- If Cap is true, the result is capped according to Entry_Family_Bound.
+ procedure Find_Enclosing_Context
+ (N : Node_Id;
+ Context : out Node_Id;
+ Context_Id : out Entity_Id;
+ Context_Decls : out List_Id);
+ -- Subsidiary routine to procedures Build_Activation_Chain_Entity and
+ -- Build_Master_Entity. Given an arbitrary node in the tree, find the
+ -- nearest enclosing body, block, package or return statement and return
+ -- its constituents. Context is the enclosing construct, Context_Id is
+ -- the scope of Context_Id and Context_Decls is the declarative list of
+ -- Context.
+
procedure Extract_Dispatching_Call
(N : Node_Id;
Call_Ent : out Entity_Id;
@@ -870,64 +882,33 @@ package body Exp_Ch9 is
-- Local variables
- Decls : List_Id;
- Par : Node_Id;
+ Context : Node_Id;
+ Context_Id : Entity_Id;
+ Decls : List_Id;
-- Start of processing for Build_Activation_Chain_Entity
begin
- -- Traverse the parent chain looking for an enclosing construct which
- -- contains an activation chain variable. The construct is either a
- -- body, a block, or an extended return.
-
- Par := Parent (N);
-
- while not Nkind_In (Par, N_Block_Statement,
- N_Entry_Body,
- N_Extended_Return_Statement,
- N_Package_Body,
- N_Package_Declaration,
- N_Subprogram_Body,
- N_Task_Body)
- loop
- Par := Parent (Par);
- end loop;
-
- -- When the enclosing construct is a package body, the activation chain
- -- variable is declared in the body, but the Activation_Chain_Entity is
- -- attached to the spec.
-
- if Nkind (Par) = N_Package_Body then
- Decls := Declarations (Par);
- Par := Unit_Declaration_Node (Corresponding_Spec (Par));
-
- elsif Nkind (Par) = N_Package_Declaration then
- Decls := Visible_Declarations (Specification (Par));
-
- elsif Nkind (Par) = N_Extended_Return_Statement then
- Decls := Return_Object_Declarations (Par);
-
- else
- Decls := Declarations (Par);
- end if;
+ Find_Enclosing_Context (N, Context, Context_Id, Decls);
-- If an activation chain entity has not been declared already, create
-- one.
- if Nkind (Par) = N_Extended_Return_Statement
- or else No (Activation_Chain_Entity (Par))
+ if Nkind (Context) = N_Extended_Return_Statement
+ or else No (Activation_Chain_Entity (Context))
then
-- Since extended return statements do not store the entity of the
-- chain, examine the return object declarations to avoid creating
-- a duplicate.
- if Nkind (Par) = N_Extended_Return_Statement
- and then Has_Activation_Chain (Par)
+ if Nkind (Context) = N_Extended_Return_Statement
+ and then Has_Activation_Chain (Context)
then
return;
end if;
declare
+ Loc : constant Source_Ptr := Sloc (Context);
Chain : Entity_Id;
Decl : Node_Id;
@@ -943,19 +924,29 @@ package body Exp_Ch9 is
-- Activate_Tasks. Task activation is the responsibility of the
-- caller.
- if Nkind (Par) /= N_Extended_Return_Statement then
- Set_Activation_Chain_Entity (Par, Chain);
+ if Nkind (Context) /= N_Extended_Return_Statement then
+ Set_Activation_Chain_Entity (Context, Chain);
end if;
Decl :=
- Make_Object_Declaration (Sloc (Par),
+ Make_Object_Declaration (Loc,
Defining_Identifier => Chain,
Aliased_Present => True,
Object_Definition =>
- New_Reference_To (RTE (RE_Activation_Chain), Sloc (Par)));
+ New_Reference_To (RTE (RE_Activation_Chain), Loc));
Prepend_To (Decls, Decl);
- Analyze (Decl);
+
+ -- Ensure that the _chain appears in the proper scope of the
+ -- context.
+
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
end;
end if;
end Build_Activation_Chain_Entity;
@@ -1073,6 +1064,127 @@ package body Exp_Ch9 is
Parameter_Associations => New_List (Concurrent_Ref (N)));
end Build_Call_With_Task;
+ -----------------------------
+ -- Build_Class_Wide_Master --
+ -----------------------------
+
+ procedure Build_Class_Wide_Master (Typ : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (Typ);
+ Master_Id : Entity_Id;
+ Master_Scope : Entity_Id;
+ Name_Id : Node_Id;
+ Related_Node : Node_Id;
+ Ren_Decl : Node_Id;
+
+ begin
+ -- Nothing to do if there is no task hierarchy
+
+ if Restriction_Active (No_Task_Hierarchy) then
+ return;
+ end if;
+
+ -- Find the declaration that created the access type. It is either a
+ -- type declaration, or an object declaration with an access definition,
+ -- in which case the type is anonymous.
+
+ if Is_Itype (Typ) then
+ Related_Node := Associated_Node_For_Itype (Typ);
+ else
+ Related_Node := Parent (Typ);
+ end if;
+
+ Master_Scope := Find_Master_Scope (Typ);
+
+ -- Nothing to do if the master scope already contains a _master entity.
+ -- The only exception to this is the following scenario:
+
+ -- Source_Scope
+ -- Transient_Scope_1
+ -- _master
+
+ -- Transient_Scope_2
+ -- use of master
+
+ -- In this case the source scope is marked as having the master entity
+ -- even though the actual declaration appears inside an inner scope. If
+ -- the second transient scope requires a _master, it cannot use the one
+ -- already declared because the entity is not visible.
+
+ Name_Id := Make_Identifier (Loc, Name_uMaster);
+
+ if not Has_Master_Entity (Master_Scope)
+ or else No (Current_Entity_In_Scope (Name_Id))
+ then
+ declare
+ Master_Decl : Node_Id;
+
+ begin
+ Set_Has_Master_Entity (Master_Scope);
+
+ -- Generate:
+ -- _master : constant Integer := Current_Master.all;
+
+ Master_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_uMaster),
+ Constant_Present => True,
+ Object_Definition =>
+ New_Reference_To (Standard_Integer, Loc),
+ Expression =>
+ Make_Explicit_Dereference (Loc,
+ New_Reference_To (RTE (RE_Current_Master), Loc)));
+
+ Insert_Action (Related_Node, Master_Decl);
+ Analyze (Master_Decl);
+
+ -- Mark the containing scope as a task master. Masters associated
+ -- with return statements are already marked at this stage (see
+ -- Analyze_Subprogram_Body).
+
+ if Ekind (Current_Scope) /= E_Return_Statement then
+ declare
+ Par : Node_Id := Related_Node;
+
+ begin
+ while Nkind (Par) /= N_Compilation_Unit loop
+ Par := Parent (Par);
+
+ -- If we fall off the top, we are at the outer level, and
+ -- the environment task is our effective master, so
+ -- nothing to mark.
+
+ if Nkind_In (Par, N_Block_Statement,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ Set_Is_Task_Master (Par);
+ exit;
+ end if;
+ end loop;
+ end;
+ end if;
+ end;
+ end if;
+
+ Master_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Typ), 'M'));
+
+ -- Generate:
+ -- Mnn renames _master;
+
+ Ren_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Master_Id,
+ Subtype_Mark => New_Reference_To (Standard_Integer, Loc),
+ Name => Name_Id);
+
+ Insert_Action (Related_Node, Ren_Decl);
+
+ Set_Master_Id (Typ, Master_Id);
+ end Build_Class_Wide_Master;
+
--------------------------------
-- Build_Corresponding_Record --
--------------------------------
@@ -2763,64 +2875,150 @@ package body Exp_Ch9 is
-- Build_Master_Entity --
-------------------------
- procedure Build_Master_Entity (E : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (E);
- P : Node_Id;
- Decl : Node_Id;
- S : Entity_Id;
+ procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (Obj_Or_Typ);
+ Context : Node_Id;
+ Context_Id : Entity_Id;
+ Decl : Node_Id;
+ Decls : List_Id;
+ Par : Node_Id;
begin
- S := Find_Master_Scope (E);
+ if Is_Itype (Obj_Or_Typ) then
+ Par := Associated_Node_For_Itype (Obj_Or_Typ);
+ else
+ Par := Parent (Obj_Or_Typ);
+ end if;
+
+ -- When creating a master for a record component which is either a task
+ -- or access-to-task, the enclosing record is the master scope and the
+ -- proper insertion point is the component list.
+
+ if Is_Record_Type (Current_Scope) then
+ Context := Par;
+ Context_Id := Current_Scope;
+ Decls := List_Containing (Context);
+
+ -- Default case for object declarations and access types. Note that the
+ -- context is updated to the nearest enclosing body, block, package or
+ -- return statement.
- -- Nothing to do if we already built a master entity for this scope
- -- or if there is no task hierarchy.
+ else
+ Find_Enclosing_Context (Par, Context, Context_Id, Decls);
+ end if;
+
+ -- Do not create a master if one already exists or there is no task
+ -- hierarchy.
- if Has_Master_Entity (S)
+ if Has_Master_Entity (Context_Id)
or else Restriction_Active (No_Task_Hierarchy)
then
return;
end if;
- -- Otherwise first build the master entity
+ -- Create a master, generate:
-- _Master : constant Master_Id := Current_Master.all;
- -- and insert it just before the current declaration
Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier =>
Make_Defining_Identifier (Loc, Name_uMaster),
- Constant_Present => True,
- Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
- Expression =>
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
+ Expression =>
Make_Explicit_Dereference (Loc,
New_Reference_To (RTE (RE_Current_Master), Loc)));
- P := Parent (E);
- Insert_Before (P, Decl);
- Analyze (Decl);
+ -- The master is inserted at the start of the declarative list of the
+ -- context.
- Set_Has_Master_Entity (S);
+ Prepend_To (Decls, Decl);
- -- Now mark the containing scope as a task master
+ -- In certain cases where transient scopes are involved, the immediate
+ -- scope is not always the proper master scope. Ensure that the master
+ -- declaration and entity appear in the same context.
- while Nkind (P) /= N_Compilation_Unit loop
- P := Parent (P);
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
- -- If we fall off the top, we are at the outer level, and the
- -- environment task is our effective master, so nothing to mark.
+ -- Mark the enclosing scope and its associated construct as being task
+ -- masters.
- if Nkind_In
- (P, N_Task_Body, N_Block_Statement, N_Subprogram_Body)
+ Set_Has_Master_Entity (Context_Id);
+
+ while Present (Context)
+ and then Nkind (Context) /= N_Compilation_Unit
+ loop
+ if Nkind_In (Context, N_Block_Statement,
+ N_Subprogram_Body,
+ N_Task_Body)
then
- Set_Is_Task_Master (P, True);
- return;
+ Set_Is_Task_Master (Context);
+ exit;
- elsif Nkind (Parent (P)) = N_Subunit then
- P := Corresponding_Stub (Parent (P));
+ elsif Nkind (Parent (Context)) = N_Subunit then
+ Context := Corresponding_Stub (Parent (Context));
end if;
+
+ Context := Parent (Context);
end loop;
end Build_Master_Entity;
+ ---------------------------
+ -- Build_Master_Renaming --
+ ---------------------------
+
+ procedure Build_Master_Renaming
+ (Ptr_Typ : Entity_Id;
+ Ins_Nod : Node_Id := Empty)
+ is
+ Loc : constant Source_Ptr := Sloc (Ptr_Typ);
+ Context : Node_Id;
+ Master_Decl : Node_Id;
+ Master_Id : Entity_Id;
+
+ begin
+ -- Nothing to do if there is no task hierarchy
+
+ if Restriction_Active (No_Task_Hierarchy) then
+ return;
+ end if;
+
+ -- Determine the proper context to insert the master renaming
+
+ if Present (Ins_Nod) then
+ Context := Ins_Nod;
+ elsif Is_Itype (Ptr_Typ) then
+ Context := Associated_Node_For_Itype (Ptr_Typ);
+ else
+ Context := Parent (Ptr_Typ);
+ end if;
+
+ -- Generate:
+ -- <Ptr_Typ>M : Master_Id renames _Master;
+
+ Master_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Ptr_Typ), 'M'));
+
+ Master_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Master_Id,
+ Subtype_Mark => New_Reference_To (RTE (RE_Master_Id), Loc),
+ Name => Make_Identifier (Loc, Name_uMaster));
+
+ Insert_Action (Context, Master_Decl);
+
+ -- The renamed master now services the access type
+
+ Set_Master_Id (Ptr_Typ, Master_Id);
+ end Build_Master_Renaming;
+
-----------------------------------------
-- Build_Private_Protected_Declaration --
-----------------------------------------
@@ -4236,7 +4434,7 @@ package body Exp_Ch9 is
Make_Object_Declaration (Loc,
Defining_Identifier => Chain,
- Aliased_Present => True,
+ Aliased_Present => True,
Object_Definition =>
New_Reference_To (RTE (RE_Activation_Chain), Loc))),
@@ -11849,6 +12047,94 @@ package body Exp_Ch9 is
Make_Integer_Literal (Loc, 0)));
end Family_Size;
+ ----------------------------
+ -- Find_Enclosing_Context --
+ ----------------------------
+
+ procedure Find_Enclosing_Context
+ (N : Node_Id;
+ Context : out Node_Id;
+ Context_Id : out Entity_Id;
+ Context_Decls : out List_Id)
+ is
+ begin
+ -- Traverse the parent chain looking for an enclosing body, block,
+ -- package or return statement.
+
+ Context := Parent (N);
+ while not Nkind_In (Context, N_Block_Statement,
+ N_Entry_Body,
+ N_Extended_Return_Statement,
+ N_Package_Body,
+ N_Package_Declaration,
+ N_Subprogram_Body,
+ N_Task_Body)
+ loop
+ Context := Parent (Context);
+ end loop;
+
+ -- Extract the constituents of the context
+
+ if Nkind (Context) = N_Extended_Return_Statement then
+ Context_Decls := Return_Object_Declarations (Context);
+ Context_Id := Return_Statement_Entity (Context);
+
+ -- Package declarations and bodies use a common library-level activation
+ -- chain or task master, therefore return the package declaration as the
+ -- proper carrier for the appropriate flag.
+
+ elsif Nkind (Context) = N_Package_Body then
+ Context_Decls := Declarations (Context);
+ Context_Id := Corresponding_Spec (Context);
+ Context := Parent (Context_Id);
+
+ if Nkind (Context) = N_Defining_Program_Unit_Name then
+ Context := Parent (Parent (Context));
+ else
+ Context := Parent (Context);
+ end if;
+
+ elsif Nkind (Context) = N_Package_Declaration then
+ Context_Decls := Visible_Declarations (Specification (Context));
+ Context_Id := Defining_Unit_Name (Specification (Context));
+
+ if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
+ Context_Id := Defining_Identifier (Context_Id);
+ end if;
+
+ else
+ Context_Decls := Declarations (Context);
+
+ if Nkind (Context) = N_Block_Statement then
+ Context_Id := Entity (Identifier (Context));
+
+ elsif Nkind (Context) = N_Entry_Body then
+ Context_Id := Defining_Identifier (Context);
+
+ elsif Nkind (Context) = N_Subprogram_Body then
+ if Present (Corresponding_Spec (Context)) then
+ Context_Id := Corresponding_Spec (Context);
+ else
+ Context_Id := Defining_Unit_Name (Specification (Context));
+
+ if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
+ Context_Id := Defining_Identifier (Context_Id);
+ end if;
+ end if;
+
+ elsif Nkind (Context) = N_Task_Body then
+ Context_Id := Corresponding_Spec (Context);
+
+ else
+ raise Program_Error;
+ end if;
+ end if;
+
+ pragma Assert (Present (Context));
+ pragma Assert (Present (Context_Id));
+ pragma Assert (Present (Context_Decls));
+ end Find_Enclosing_Context;
+
-----------------------
-- Find_Master_Scope --
-----------------------
@@ -11857,7 +12143,7 @@ package body Exp_Ch9 is
S : Entity_Id;
begin
- -- In Ada2005, the master is the innermost enclosing scope that is not
+ -- In Ada 2005, the master is the innermost enclosing scope that is not
-- transient. If the enclosing block is the rewriting of a call or the
-- scope is an extended return statement this is valid master. The
-- master in an extended return is only used within the return, and is
diff --git a/gcc/ada/exp_ch9.ads b/gcc/ada/exp_ch9.ads
index 13e3f796ef0..3bbbf0dc719 100644
--- a/gcc/ada/exp_ch9.ads
+++ b/gcc/ada/exp_ch9.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, 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- --
@@ -50,28 +50,32 @@ package Exp_Ch9 is
-- Task_Id of the associated task as the parameter. The caller is
-- responsible for analyzing and resolving the resulting tree.
+ procedure Build_Class_Wide_Master (Typ : Entity_Id);
+ -- Given an access-to-limited class-wide type or an access-to-limited
+ -- interface, ensure that the designated type has a _master and generate
+ -- a renaming of the said master to service the access type.
+
function Build_Entry_Names (Conc_Typ : Entity_Id) return Node_Id;
-- Create the statements which populate the entry names array of a task or
-- protected type. The statements are wrapped inside a block due to a local
-- declaration.
- procedure Build_Master_Entity (E : Entity_Id);
- -- Given an entity E for the declaration of an object containing tasks
- -- or of a type declaration for an allocator whose designated type is a
- -- task or contains tasks, this routine marks the appropriate enclosing
- -- context as a master, and also declares a variable called _Master in
- -- the current declarative part which captures the value of Current_Master
- -- (if not already built by a prior call). We build this object (instead
- -- of just calling Current_Master) for two reasons. First it is clearly
- -- more efficient to call Current_Master only once for a bunch of tasks
- -- in the same declarative part, and second it makes things easier in
- -- generating the initialization routines, since they can just reference
- -- the object _Master by name, and they will get the proper Current_Master
- -- value at the outer level, and copy in the parameter value for the outer
- -- initialization call if the call is for a nested component). Note that
- -- in the case of nested packages, we only really need to make one such
- -- object at the outer level, but it is much easier to generate one per
- -- declarative part.
+ procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id);
+ -- Given the name of an object or a type which is either a task, contains
+ -- tasks or designates tasks, create a _master in the appropriate scope
+ -- which captures the value of Current_Master. Mark the nearest enclosing
+ -- body or block as being a task master.
+
+ procedure Build_Master_Renaming
+ (Ptr_Typ : Entity_Id;
+ Ins_Nod : Node_Id := Empty);
+ -- Given an access type Ptr_Typ whose designated type is either a task or
+ -- contains tasks, create a renaming of the form:
+ --
+ -- <Ptr_Typ>M : Master_Id renames _Master;
+ --
+ -- where _master denotes the task master of the enclosing context. Ins_Nod
+ -- is used to provide a specific insertion node for the renaming.
function Build_Private_Protected_Declaration (N : Node_Id) return Entity_Id;
-- A subprogram body without a previous spec that appears in a protected
@@ -266,7 +270,7 @@ package Exp_Ch9 is
function Find_Master_Scope (E : Entity_Id) return Entity_Id;
-- When a type includes tasks, a master entity is created in the scope, to
-- be used by the runtime during activation. In general the master is the
- -- immediate scope in which the type is declared, but in Ada2005, in the
+ -- immediate scope in which the type is declared, but in Ada 2005, in the
-- presence of synchronized classwide interfaces, the immediate scope of
-- an anonymous access type may be a transient scope, which has no run-time
-- presence. In this case, the scope of the master is the innermost scope
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index 5f9cd8326f1..21745288abf 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -3771,12 +3771,16 @@ package body Exp_Disp is
-- Start of processing for Check_Premature_Freezing
begin
+ -- Note that if the type is a (subtype of) a generic actual, the
+ -- actual will have been frozen by the instantiation.
+
if Present (N)
and then Is_Private_Type (Typ)
and then No (Full_View (Typ))
and then not Is_Generic_Type (Typ)
and then not Is_Tagged_Type (Typ)
and then not Is_Frozen (Typ)
+ and then not Is_Generic_Actual_Type (Typ)
then
Error_Msg_Sloc := Sloc (Subp);
Error_Msg_NE
diff --git a/gcc/ada/exp_strm.adb b/gcc/ada/exp_strm.adb
index c88c789432e..987556a84ad 100644
--- a/gcc/ada/exp_strm.adb
+++ b/gcc/ada/exp_strm.adb
@@ -1592,7 +1592,7 @@ package body Exp_Strm is
begin
-- (Ada 2005: AI-441): Set the null-excluding attribute because it has
- -- no semantic meaning in Ada 95 but it is a requirement in Ada2005.
+ -- no semantic meaning in Ada 95 but it is a requirement in Ada 2005.
Profile := New_List (
Make_Parameter_Specification (Loc,
@@ -1632,7 +1632,7 @@ package body Exp_Strm is
-- Construct function specification
-- (Ada 2005: AI-441): Set the null-excluding attribute because it has
- -- no semantic meaning in Ada 95 but it is a requirement in Ada2005.
+ -- no semantic meaning in Ada 95 but it is a requirement in Ada 2005.
Spec :=
Make_Function_Specification (Loc,
@@ -1676,7 +1676,7 @@ package body Exp_Strm is
-- Construct procedure specification
-- (Ada 2005: AI-441): Set the null-excluding attribute because it has
- -- no semantic meaning in Ada 95 but it is a requirement in Ada2005.
+ -- no semantic meaning in Ada 95 but it is a requirement in Ada 2005.
Spec :=
Make_Procedure_Specification (Loc,
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 295006a29c3..dd58b017d24 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -1921,11 +1921,11 @@ package body Exp_Util is
then
null;
- -- In Ada95 nothing to be done if the type of the expression is limited,
+ -- In Ada 95 nothing to be done if the type of the expression is limited
-- because in this case the expression cannot be copied, and its use can
-- only be by reference.
- -- In Ada2005, the context can be an object declaration whose expression
+ -- In Ada 2005 the context can be an object declaration whose expression
-- is a function that returns in place. If the nominal subtype has
-- unknown discriminants, the call still provides constraints on the
-- object, and we have to create an actual subtype from it.
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index e8078648892..8c42fed255b 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -1407,7 +1407,11 @@ package body Freeze is
Decl := Unit_Declaration_Node (E);
if Nkind (Decl) = N_Subprogram_Renaming_Declaration then
- Build_And_Analyze_Renamed_Body (Decl, E, After);
+ if Error_Posted (Decl) then
+ Set_Has_Completion (E);
+ else
+ Build_And_Analyze_Renamed_Body (Decl, E, After);
+ end if;
elsif Nkind (Decl) = N_Subprogram_Declaration
and then Present (Corresponding_Body (Decl))
@@ -1616,9 +1620,9 @@ package body Freeze is
-- Start of processing for Check_Current_Instance
begin
- -- In Ada95, the (imprecise) rule is that the current instance of a
- -- limited type is aliased. In Ada2005, limitedness must be explicit:
- -- either a tagged type, or a limited record.
+ -- In Ada 95, the (imprecise) rule is that the current instance
+ -- of a limited type is aliased. In Ada 2005, limitedness must be
+ -- explicit: either a tagged type, or a limited record.
if Is_Limited_Type (Rec_Type)
and then (Ada_Version < Ada_2005 or else Is_Tagged_Type (Rec_Type))
@@ -1646,6 +1650,7 @@ package body Freeze is
if Nkind (Decl) = N_Full_Type_Declaration then
declare
Tdef : constant Node_Id := Type_Definition (Decl);
+
begin
if Nkind (Tdef) = N_Modular_Type_Definition then
declare
diff --git a/gcc/ada/g-debpoo.ads b/gcc/ada/g-debpoo.ads
index 7e610c240cc..e87c0e4b18d 100644
--- a/gcc/ada/g-debpoo.ads
+++ b/gcc/ada/g-debpoo.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, 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- --
@@ -29,7 +29,7 @@
-- --
------------------------------------------------------------------------------
--- This packages provides a special implementation of the Ada95 storage pools
+-- This packages provides a special implementation of the Ada 95 storage pools
-- The goal of this debug pool is to detect incorrect uses of memory
-- (multiple deallocations, access to invalid memory,...). Errors are reported
diff --git a/gcc/ada/g-trasym-unimplemented.adb b/gcc/ada/g-trasym-unimplemented.adb
deleted file mode 100644
index f020fff497a..00000000000
--- a/gcc/ada/g-trasym-unimplemented.adb
+++ /dev/null
@@ -1,70 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- G N A T . T R A C E B A C K . S Y M B O L I C --
--- --
--- B o d y --
--- --
--- Copyright (C) 1999-2010, AdaCore --
--- --
--- 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- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception 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/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- Version used on unimplemented targets
-
--- Run-time symbolic traceback is currently supported on the following
--- targets:
-
--- HP-UX
--- IRIX
--- GNU/Linux x86
--- AIX
--- Solaris sparc
--- Tru64
--- OpenVMS/Alpha
--- Windows NT/XP/Vista
-
--- This version is used on all other targets, it generates a warning at
--- compile time if it is with'ed, and the bodies generate messages saying
--- that the functions are not implemented.
-
-package body GNAT.Traceback.Symbolic is
-
- ------------------------
- -- Symbolic_Traceback --
- ------------------------
-
- function Symbolic_Traceback (Traceback : Tracebacks_Array) return String
- is
- pragma Unreferenced (Traceback);
- begin
- return "Symbolic_Traceback not implemented on this target";
- end Symbolic_Traceback;
-
- function Symbolic_Traceback (E : Exception_Occurrence) return String
- is
- pragma Unreferenced (E);
- begin
- return "Symbolic_Traceback not implemented on this target";
- end Symbolic_Traceback;
-
-end GNAT.Traceback.Symbolic;
diff --git a/gcc/ada/g-trasym-unimplemented.ads b/gcc/ada/g-trasym-unimplemented.ads
deleted file mode 100644
index 8d1f2eeb725..00000000000
--- a/gcc/ada/g-trasym-unimplemented.ads
+++ /dev/null
@@ -1,64 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- G N A T . T R A C E B A C K . S Y M B O L I C --
--- --
--- S p e c --
--- --
--- Copyright (C) 1999-2010, AdaCore --
--- --
--- 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- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception 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/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- Version used on unimplemented targets
-
--- Run-time symbolic traceback is currently supported on the following
--- targets:
-
--- HP-UX hppa and ia64
--- IRIX
--- GNU/Linux x86, x86_64, ia64
--- AIX
--- Solaris sparc and x86
--- Tru64
--- OpenVMS/Alpha
--- Windows NT/XP/Vista
-
--- This version is used on all other targets, it generates a warning at
--- compile time if it is with'ed, and the bodies generate messages saying
--- that the functions are not implemented.
-
-with Ada.Exceptions; use Ada.Exceptions;
-
-package GNAT.Traceback.Symbolic is
- pragma Elaborate_Body;
-
--- pragma Compile_Time_Warning
--- (True, "symbolic traceback not implemented on this target");
-
- function Symbolic_Traceback (Traceback : Tracebacks_Array) return String;
- -- Build a string containing a symbolic traceback of the given call chain
-
- function Symbolic_Traceback (E : Exception_Occurrence) return String;
- -- Build string containing symbolic traceback of given exception occurrence
-
-end GNAT.Traceback.Symbolic;
diff --git a/gcc/ada/g-trasym.adb b/gcc/ada/g-trasym.adb
index 1b1ddffd93a..ac2444e001e 100644
--- a/gcc/ada/g-trasym.adb
+++ b/gcc/ada/g-trasym.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1999-2010, AdaCore --
+-- Copyright (C) 1999-2011, AdaCore --
-- --
-- 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- --
@@ -29,122 +29,49 @@
-- --
------------------------------------------------------------------------------
--- Run-time symbolic traceback support
+-- This is the default implementation for platforms where the full capability
+-- is not supported. It returns tracebacks as lists of LF separated strings of
+-- the form "0x..." corresponding to the addresses.
-with System.Soft_Links;
with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
+with System.Address_Image;
package body GNAT.Traceback.Symbolic is
- pragma Linker_Options ("-laddr2line");
- pragma Linker_Options ("-lbfd");
- pragma Linker_Options ("-liberty");
-
- package TSL renames System.Soft_Links;
-
- -- To perform the raw addresses to symbolic form translation we rely on a
- -- libaddr2line symbolizer which examines debug info from a provided
- -- executable file name, and an absolute path is needed to ensure the file
- -- is always found. This is "__gnat_locate_exec_on_path (gnat_argv [0])"
- -- for our executable file, a fairly heavy operation so we cache the
- -- result.
-
- Exename : System.Address;
- -- Pointer to the name of the executable file to be used on all
- -- invocations of the libaddr2line symbolization service.
-
- Exename_Resolved : Boolean := False;
- -- Flag to indicate whether we have performed the executable file name
- -- resolution already. Relying on a not null Exename for this purpose
- -- would be potentially inefficient as this is what we will get if the
- -- resolution attempt fails.
-
------------------------
-- Symbolic_Traceback --
------------------------
- function Symbolic_Traceback (Traceback : Tracebacks_Array) return String is
-
- procedure convert_addresses
- (filename : System.Address;
- addrs : System.Address;
- n_addrs : Integer;
- buf : System.Address;
- len : System.Address);
- pragma Import (C, convert_addresses, "convert_addresses");
- -- This is the procedure version of the Ada-aware addr2line. It places
- -- in BUF a string representing the symbolic translation of the N_ADDRS
- -- raw addresses provided in ADDRS, looked up in debug information from
- -- FILENAME. LEN points to an integer which contains the size of the
- -- BUF buffer at input and the result length at output.
- --
- -- This procedure is provided by libaddr2line on targets that support
- -- it. A dummy version is in adaint.c for other targets so that build
- -- of shared libraries doesn't generate unresolved symbols.
- --
- -- Note that this procedure is *not* thread-safe.
-
- type Argv_Array is array (0 .. 0) of System.Address;
- gnat_argv : access Argv_Array;
- pragma Import (C, gnat_argv, "gnat_argv");
-
- function locate_exec_on_path
- (c_exename : System.Address) return System.Address;
- pragma Import (C, locate_exec_on_path, "__gnat_locate_exec_on_path");
-
- Res : String (1 .. 256 * Traceback'Length);
- Len : Integer;
-
- use type System.Address;
-
+ function Symbolic_Traceback (Traceback : Tracebacks_Array) return String
+ is
begin
- -- The symbolic translation of an empty set of addresses is an empty
- -- string.
-
if Traceback'Length = 0 then
return "";
- end if;
- -- If our input set of raw addresses is not empty, resort to the
- -- libaddr2line service to symbolize it all.
-
- -- Compute, cache and provide the absolute path to our executable file
- -- name as the binary file where the relevant debug information is to be
- -- found. If the executable file name resolution fails, we have no
- -- sensible basis to invoke the symbolizer at all.
-
- -- Protect all this against concurrent accesses explicitly, as the
- -- underlying services are potentially thread unsafe.
-
- TSL.Lock_Task.all;
-
- if not Exename_Resolved then
- Exename := locate_exec_on_path (gnat_argv (0));
- Exename_Resolved := True;
- end if;
-
- if Exename /= System.Null_Address then
- Len := Res'Length;
- convert_addresses
- (Exename, Traceback'Address, Traceback'Length,
- Res (1)'Address, Len'Address);
- end if;
-
- TSL.Unlock_Task.all;
-
- -- Return what the addr2line symbolizer has produced if we have called
- -- it (the executable name resolution succeeded), or an empty string
- -- otherwise.
-
- if Exename /= System.Null_Address then
- return Res (1 .. Len);
else
- return "";
+ declare
+ Img : String := System.Address_Image (Traceback (Traceback'First));
+
+ Result : String (1 .. (Img'Length + 3) * Traceback'Length);
+ Last : Natural := 0;
+
+ begin
+ for J in Traceback'Range loop
+ Img := System.Address_Image (Traceback (J));
+ Result (Last + 1 .. Last + 2) := "0x";
+ Last := Last + 2;
+ Result (Last + 1 .. Last + Img'Length) := Img;
+ Last := Last + Img'Length + 1;
+ Result (Last) := ASCII.LF;
+ end loop;
+
+ return Result (1 .. Last);
+ end;
end if;
-
end Symbolic_Traceback;
- function Symbolic_Traceback (E : Exception_Occurrence) return String is
+ function Symbolic_Traceback (E : Exception_Occurrence) return String
+ is
begin
return Symbolic_Traceback (Tracebacks (E));
end Symbolic_Traceback;
diff --git a/gcc/ada/g-trasym.ads b/gcc/ada/g-trasym.ads
index 44d85ae4041..4b30600adb3 100644
--- a/gcc/ada/g-trasym.ads
+++ b/gcc/ada/g-trasym.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1999-2010, AdaCore --
+-- Copyright (C) 1999-2011, AdaCore --
-- --
-- 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- --
@@ -31,16 +31,20 @@
-- Run-time symbolic traceback support
--- This capability is currently supported on the following targets:
+-- The full capability is currently supported on the following targets:
--- HP-UX hppa and ia64
+-- HP-UX ia64
-- IRIX
-- GNU/Linux x86, x86_64, ia64
--- AIX
+-- FreeBSD x86, x86_64
-- Solaris sparc and x86
-- Tru64
--- OpenVMS/Alpha
--- Windows NT/XP/Vista
+-- OpenVMS Alpha and ia64
+-- Windows
+
+-- Note: on targets other than those listed above, a dummy implementation of
+-- the body returns a series of LF separated strings of the form "0x..."
+-- corresponding to the addresses.
-- The routines provided in this package assume that your application has
-- been compiled with debugging information turned on, since this information
@@ -77,14 +81,17 @@
-- libraries. However, the OS should be at least v7.3-1 and OS patch
-- VMS731_TRACE-V0100 must be applied in order to use this package.
+-- On platforms where the full capability is not supported, function
+-- Symbolic_Traceback return a list of addresses expressed as "0x..."
+-- separated by line feed.
+
with Ada.Exceptions; use Ada.Exceptions;
package GNAT.Traceback.Symbolic is
pragma Elaborate_Body;
function Symbolic_Traceback (Traceback : Tracebacks_Array) return String;
- -- Build a string containing a symbolic traceback of the given call chain
- --
+ -- Build a string containing a symbolic traceback of the given call chain.
-- Note: This procedure may be installed by Set_Trace_Decorator, to get a
-- symbolic traceback on all exceptions raised (see GNAT.Exception_Traces).
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 9f25fc26d92..81e14f20c34 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -46,6 +46,7 @@ RMDIR = rm -rf
# Extra flags to pass to recursive makes.
COMMON_ADAFLAGS= -gnatpg -gnata
+WARN_ADAFLAGS= -W -Wall
BOOT_ADAFLAGS= $(COMMON_ADAFLAGS)
ifeq ($(CROSS),)
@@ -56,17 +57,19 @@ else
ADAFLAGS= $(COMMON_ADAFLAGS)
endif
-ALL_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(ADAFLAGS)
+ALL_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(ADAFLAGS) $(WARN_ADAFLAGS)
FORCE_DEBUG_ADAFLAGS = -g
ADA_CFLAGS =
ADA_INCLUDES = -nostdinc -I- -I. -Iada -I$(srcdir)/ada -I$(srcdir)/ada/gcc-interface
ADA_INCLUDE_DIR = $(libsubdir)/adainclude
ADA_RTL_OBJ_DIR = $(libsubdir)/adalib
+# We do not want the WARN_CFLAGS of the compiler in Ada as it is for C/C++.
+COMMON_FLAGS_TO_PASS = $(filter-out -pedantic -W%, $(FLAGS_TO_PASS))
ADA_FLAGS_TO_PASS = \
"ADA_FOR_BUILD=$(ADA_FOR_BUILD)" \
"ADA_INCLUDE_DIR=$(ADA_INCLUDE_DIR)" \
"ADA_RTL_OBJ_DIR=$(ADA_RTL_OBJ_DIR)" \
- "ADAFLAGS=$(ADAFLAGS)" \
+ "ADAFLAGS=$(ADAFLAGS) $(WARN_ADAFLAGS)" \
"ADA_FOR_TARGET=$(ADA_FOR_TARGET)" \
"INSTALL=$(INSTALL)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
@@ -99,14 +102,12 @@ ifeq ($(build), $(host))
# This is a regular native. So use the compiler from our current build
# tree.
ADA_TOOLS_FLAGS_TO_PASS=\
- "CC=../../xgcc -B../../" \
- "CFLAGS=$(CFLAGS)" \
- "exeext=$(exeext)" \
- "ADAFLAGS=$(ADAFLAGS)" \
- "ADA_INCLUDES=-I../rts" \
- "GNATMAKE=../../gnatmake" \
- "GNATLINK=../../gnatlink" \
- "GNATBIND=../../gnatbind"
+ CC="../../xgcc -B../../" \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ ADA_INCLUDES="-I- -I../rts" \
+ GNATMAKE="../../gnatmake" \
+ GNATLINK="../../gnatlink" \
+ GNATBIND="../../gnatbind"
else
# This is a regular cross compiler. Use the native compiler to compile
# the tools.
@@ -117,7 +118,7 @@ ifeq ($(build), $(host))
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
ADA_INCLUDES="-I$(RTS_DIR)../adainclude -I$(RTS_DIR)" \
GNATMAKE="gnatmake" \
GNATBIND="gnatbind" \
@@ -139,7 +140,7 @@ else
# built runtime.
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
ADA_INCLUDES="-I../rts" \
GNATMAKE="$(GNATMAKE_FOR_HOST)" \
GNATBIND="$(GNATBIND_FOR_HOST)" \
@@ -151,7 +152,7 @@ else
RTS_DIR:=$(strip $(subst \,/,$(shell $(GNATLS_FOR_HOST) -v | grep adalib )))
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
ADA_INCLUDES="-I$(RTS_DIR)../adainclude -I$(RTS_DIR)" \
GNATMAKE="$(GNATMAKE_FOR_HOST)" \
GNATBIND="$(GNATBIND_FOR_HOST)" \
@@ -547,9 +548,7 @@ gnatbind$(exeext): ada/b_gnatb.o $(CONFIG_H) $(GNATBIND_OBJS) ggc-none.o libcomm
# use target-gcc target-gnatmake target-gnatbind target-gnatlink
gnattools: $(GCC_PARTS) $(CONFIG_H) prefix.o force
- $(MAKE) -C ada $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
- ADA_INCLUDES="-I- -I../rts"\
- CC="../../xgcc -B../../" GNATBIND="../../gnatbind" gnattools1
+ $(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools1
$(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools2
regnattools:
@@ -566,7 +565,7 @@ canadian-gnattools: force
$(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools2
gnatlib gnatlib-sjlj gnatlib-zcx gnatlib-shared: ada/s-oscons.ads force
- $(MAKE) -C ada $(FLAGS_TO_PASS) \
+ $(MAKE) -C ada $(COMMON_FLAGS_TO_PASS) \
GNATLIBFLAGS="$(GNATLIBFLAGS)" \
GNATLIBCFLAGS="$(GNATLIBCFLAGS)" \
TARGET_LIBGCC2_CFLAGS="$(TARGET_LIBGCC2_CFLAGS)" \
@@ -578,11 +577,6 @@ gnatlib gnatlib-sjlj gnatlib-zcx gnatlib-shared: ada/s-oscons.ads force
# use only for native compiler
gnatlib_and_tools: gnatlib gnattools
-# use cross-gcc
-gnat-cross: force
- make $(GNAT1_ADA_OBJS) CC="gcc -B../stage1/" CFLAGS="-S -gnatp" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) HOST_CFLAGS= HOST_CC=cc
-
# Build hooks:
ada.all.cross:
@@ -966,14 +960,14 @@ ada.install-common:
#
-if [ -f gnat1$(exeext) ] ; \
then \
- $(MAKE) $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib; \
+ $(MAKE) $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib; \
fi
install-gnatlib:
- $(MAKE) -C ada $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib$(LIBGNAT_TARGET)
+ $(MAKE) -C ada $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib$(LIBGNAT_TARGET)
install-gnatlib-obj:
- $(MAKE) -C ada $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib-obj
+ $(MAKE) -C ada $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib-obj
ada.install-man:
ada.install-plugin:
@@ -1129,50 +1123,7 @@ $(check_acats_targets): check-acats%:
export testdir; cd $(ACATSDIR)$* && $(SHELL) $${testdir}/run_acats $$chapters
.PHONY: check-acats $(check_acats_targets)
-
-# Bootstrapping targets for just GNAT - use the same stage directories
-gnatboot: force
- -$(RM) gnatboot3
- $(MAKE) gnat1$(exeext) gnatbind$(exeext) CC="$(CC)" \
- CFLAGS="$(CFLAGS)"
- $(MAKE) gnatboot2 BOOT_CFLAGS="$(BOOT_CFLAGS)" \
- BOOT_ADAFLAGS="$(BOOT_ADAFLAGS)" \
- LDFLAGS="$(BOOT_LDFLAGS)"
-
-gnatboot2: force
- $(MAKE) gnatstage1
- $(MAKE) gnat1$(exeext) gnatbind$(exeext) CC="gcc -B../stage1/"\
- CFLAGS="$(BOOT_CFLAGS)" \
- ADAFLAGS="$(BOOT_ADAFLAGS)"\
- LDFLAGS="$(BOOT_LDFLAGS)" \
- GNATBIND="../stage1/gnatbind"
- $(MAKE) gnatboot3 BOOT_CFLAGS="$(BOOT_CFLAGS)" \
- BOOT_ADAFLAGS="$(BOOT_ADAFLAGS)" \
- LDFLAGS="$(BOOT_LDFLAGS)"
-
-gnatboot3:
- $(MAKE) gnatstage2
- $(MAKE) gnat1$(exeext) gnatbind$(exeext) CC="gcc -B../stage2/"\
- CFLAGS="$(BOOT_CFLAGS)" \
- ADAFLAGS="$(BOOT_ADAFLAGS)"\
- LDFLAGS="$(BOOT_LDFLAGS)" \
- GNATBIND="../stage2/gnatbind"
-
-gnatstage1: force
- -$(MKDIR) stage1
- -$(MKDIR) stage1/ada
- -$(MV) gnat1$(exeext) gnatbind$(exeext) stage1
- -$(MV) ada/*$(objext) ada/*.ali stage1/ada
- -$(MV) ada/stamp-* stage1/ada
-
-gnatstage2: force
- -$(MKDIR) stage2
- -$(MKDIR) stage2/ada
- -$(MV) gnat1$(exeext) gnatbind$(exeext) stage2
- -$(MV) ada/*$(objext) ada/*.ali stage2/ada
- -$(MV) ada/stamp-* stage2/ada
-
# Compiling object files from source files.
# Note that dependencies on obstack.h are not written
@@ -3759,9 +3710,9 @@ ada/sem_aggr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/par_sco.ads ada/put_alfa.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_aggr.adb \
+ ada/opt.adb ada/output.ads ada/par_sco.ads ada/put_alfa.ads \
+ ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
+ ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_aggr.adb \
ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_cat.ads \
ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
ada/sem_ch13.adb ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index a6c54e8d81d..160a15e013c 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -105,20 +105,18 @@ TEXI2PDF = texi2pdf
GNATBIND_FLAGS = -static -x
ADA_CFLAGS =
ADAFLAGS = -W -Wall -gnatpg -gnata
-SOME_ADAFLAGS =-gnata
FORCE_DEBUG_ADAFLAGS = -g
-NO_SIBLING_ADAFLAGS=-fno-optimize-sibling-calls
-NO_REORDER_ADAFLAGS=-fno-toplevel-reorder
-GNATLIBFLAGS = -gnatpg -nostdinc
+NO_SIBLING_ADAFLAGS = -fno-optimize-sibling-calls
+NO_REORDER_ADAFLAGS = -fno-toplevel-reorder
+GNATLIBFLAGS = -W -Wall -gnatpg -nostdinc
GNATLIBCFLAGS = -g -O2
PICFLAG_FOR_TARGET = @PICFLAG_FOR_TARGET@
# Pretend that _Unwind_GetIPInfo is available for the target by default. This
# should be autodetected during the configuration of libada and passed down to
# here, but we need something for --disable-libada and hope for the best.
-GNATLIBCFLAGS_FOR_C = $(GNATLIBCFLAGS) $(PICFLAG_FOR_TARGET) -fexceptions \
- -DIN_RTS -DHAVE_GETIPINFO
+GNATLIBCFLAGS_FOR_C = -W -Wall $(GNATLIBCFLAGS) $(PICFLAG_FOR_TARGET) \
+ -fexceptions -DIN_RTS -DHAVE_GETIPINFO
ALL_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(ADAFLAGS)
-MOST_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(SOME_ADAFLAGS)
THREAD_KIND = native
THREADSLIB =
GMEM_LIB =
@@ -231,8 +229,7 @@ all.indirect: Makefile ../gnat1$(exeext)
INTERNAL_CFLAGS = @CROSS@ -DIN_GCC
# This is the variable actually used when we compile.
-LOOSE_CFLAGS = `echo $(CFLAGS) $(WARN2_CFLAGS)|sed -e 's/-pedantic//g' -e 's/-Wtraditional//g'`
-ALL_CFLAGS = $(INTERNAL_CFLAGS) $(T_CFLAGS) $(LOOSE_CFLAGS)
+ALL_CFLAGS = $(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS)
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS)
@@ -469,8 +466,6 @@ ifeq ($(strip $(filter-out m68k% wrs vx%,$(targ))),)
g-socthi.ads<g-socthi-vxworks.ads \
g-socthi.adb<g-socthi-vxworks.adb \
g-stsifd.adb<g-stsifd-sockets.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-vxworks-m68k.ads
TOOLS_TARGET_PAIRS=mlib-tgt-specific.adb<mlib-tgt-specific-vxworks.adb
@@ -512,8 +507,6 @@ ifeq ($(strip $(filter-out e500% powerpc% wrs vxworks,$(targ))),)
g-socthi.ads<g-socthi-vxworks.ads \
g-socthi.adb<g-socthi-vxworks.adb \
g-stsifd.adb<g-stsifd-sockets.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
$(ATOMICS_TARGET_PAIRS) \
$(ATOMICS_BUILTINS_TARGET_PAIRS)
@@ -580,6 +573,8 @@ ifeq ($(strip $(filter-out e500% powerpc% wrs vxworks,$(targ))),)
endif
endif
EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o s-vxwexc.o
+ EXTRA_LIBGNAT_OBJS+=sigtramp-ppcvxw.o
+ EXTRA_LIBGNAT_SRCS+=sigtramp-ppcvxw.c
endif
endif
@@ -613,8 +608,6 @@ ifeq ($(strip $(filter-out powerpc% e500v2 wrs vxworksae,$(targ))),)
s-vxwext.adb<s-vxwext-noints.adb \
s-vxwext.ads<s-vxwext-vthreads.ads \
s-vxwork.ads<s-vxwork-ppc.ads \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-vxworks-ppc-vthread.ads \
$(ATOMICS_TARGET_PAIRS) \
$(ATOMICS_BUILTINS_TARGET_PAIRS)
@@ -626,6 +619,9 @@ ifeq ($(strip $(filter-out powerpc% e500v2 wrs vxworksae,$(targ))),)
EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o s-vxwexc.o
EXTRA_GNATRTL_TASKING_OBJS=s-vxwork.o s-vxwext.o
+ EXTRA_LIBGNAT_SRCS+=sigtramp-ppcvxw.c
+ EXTRA_LIBGNAT_OBJS+=sigtramp-ppcvxw.o
+
# Extra pairs for the vthreads runtime
ifeq ($(strip $(filter-out vthreads,$(THREAD_KIND))),)
LIBGNAT_TARGET_PAIRS += \
@@ -676,8 +672,6 @@ ifeq ($(strip $(filter-out e500% powerpc% wrs vxworksmils,$(targ))),)
s-thread.adb<s-thread-ae653.adb \
s-tpopsp.adb<s-tpopsp-vxworks.adb \
s-vxwork.ads<s-vxwork-ppc.ads \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-vxworks-ppc.ads \
$(ATOMICS_TARGET_PAIRS) \
$(ATOMICS_BUILTINS_TARGET_PAIRS) \
@@ -690,8 +684,8 @@ ifeq ($(strip $(filter-out e500% powerpc% wrs vxworksmils,$(targ))),)
EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o s-thread.o s-vxwexc.o
EXTRA_GNATRTL_TASKING_OBJS=s-vxwork.o s-vxwext.o
- EXTRA_LIBGNAT_SRCS+=vx_stack_info.c
- EXTRA_LIBGNAT_OBJS+=vx_stack_info.o
+ EXTRA_LIBGNAT_SRCS+=vx_stack_info.c sigtramp-ppcvxw.c
+ EXTRA_LIBGNAT_OBJS+=vx_stack_info.o sigtramp-ppcvxw.o
GNATRTL_SOCKETS_OBJS =
ifeq ($(strip $(filter-out yes,$(TRACE))),)
@@ -728,8 +722,6 @@ ifeq ($(strip $(filter-out %86 wrs vxworksae vxworksmils,$(targ))),)
s-vxwext.adb<s-vxwext-noints.adb \
s-vxwext.ads<s-vxwext-vthreads.ads \
s-vxwork.ads<s-vxwork-x86.ads \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
$(ATOMICS_TARGET_PAIRS) \
$(X86_TARGET_PAIRS) \
system.ads<system-vxworks-x86.ads
@@ -789,8 +781,6 @@ ifeq ($(strip $(filter-out sparc% wrs vx%,$(targ))),)
g-socthi.ads<g-socthi-vxworks.ads \
g-socthi.adb<g-socthi-vxworks.adb \
g-stsifd.adb<g-stsifd-sockets.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-vxworks-sparcv9.ads \
TOOLS_TARGET_PAIRS=\
@@ -825,8 +815,6 @@ ifeq ($(strip $(filter-out %86 wrs vxworks,$(targ))),)
g-socthi.ads<g-socthi-vxworks.ads \
g-socthi.adb<g-socthi-vxworks.adb \
g-stsifd.adb<g-stsifd-sockets.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
$(ATOMICS_TARGET_PAIRS) \
$(X86_TARGET_PAIRS)
@@ -861,7 +849,7 @@ ifeq ($(strip $(filter-out %86 wrs vxworks,$(targ))),)
system.ads<system-vxworks-x86-rtp.ads
EXTRA_GNATRTL_NONTASKING_OBJS=s-vxwexc.o
- EXTRA_LIBGNAT_SRCS+=affinity.o
+ EXTRA_LIBGNAT_OBJS+=affinity.o
EXTRA_LIBGNAT_SRCS+=affinity.c
else
ifeq ($(strip $(filter-out kernel-smp, $(THREAD_KIND))),)
@@ -922,8 +910,6 @@ ifeq ($(strip $(filter-out arm% coff wrs vx%,$(targ))),)
g-socthi.ads<g-socthi-vxworks.ads \
g-socthi.adb<g-socthi-vxworks.adb \
g-stsifd.adb<g-stsifd-sockets.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-vxworks-arm.ads
TOOLS_TARGET_PAIRS=\
@@ -960,8 +946,6 @@ ifeq ($(strip $(filter-out mips% wrs vx%,$(targ))),)
g-socthi.ads<g-socthi-vxworks.ads \
g-socthi.adb<g-socthi-vxworks.adb \
g-stsifd.adb<g-stsifd-sockets.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-vxworks-mips.ads
TOOLS_TARGET_PAIRS=\
@@ -1271,9 +1255,7 @@ ifeq ($(strip $(filter-out s390% linux%,$(arch) $(osys))),)
s-tasinf.ads<s-tasinf-linux.ads \
s-tasinf.adb<s-tasinf-linux.adb \
s-taspri.ads<s-taspri-posix-noaltstack.ads \
- s-tpopsp.adb<s-tpopsp-posix-foreign.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb
+ s-tpopsp.adb<s-tpopsp-posix-foreign.adb
LIBGNAT_TARGET_PAIRS_32 = \
system.ads<system-linux-s390.ads
@@ -1447,9 +1429,7 @@ ifeq ($(strip $(filter-out rtems%,$(osys))),)
s-taspri.ads<s-taspri-posix.ads \
s-tpopsp.adb<s-tpopsp-rtems.adb \
s-stchop.adb<s-stchop-rtems.adb \
- s-interr.adb<s-interr-hwint.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb
+ s-interr.adb<s-interr-hwint.adb
endif
ifeq ($(strip $(filter-out alpha% dec osf%,$(targ))),)
@@ -1914,8 +1894,6 @@ ifeq ($(strip $(filter-out sparc% linux%,$(arch) $(osys))),)
s-tpopsp.adb<s-tpopsp-tls.adb
LIBGNAT_TARGET_PAIRS_32 = \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-linux-sparc.ads
LIBGNAT_TARGET_PAIRS_64 = \
@@ -1955,8 +1933,6 @@ ifeq ($(strip $(filter-out hppa% linux%,$(arch) $(osys))),)
s-tasinf.adb<s-tasinf-linux.adb \
s-taspri.ads<s-taspri-posix-noaltstack.ads \
s-tpopsp.adb<s-tpopsp-posix-foreign.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-linux-hppa.ads
TOOLS_TARGET_PAIRS = \
@@ -2079,8 +2055,6 @@ ifeq ($(strip $(filter-out alpha% linux%,$(arch) $(osys))),)
s-tasinf.adb<s-tasinf-linux.adb \
s-tpopsp.adb<s-tpopsp-posix-foreign.adb \
s-taspri.ads<s-taspri-posix-noaltstack.ads \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb \
system.ads<system-linux-alpha.ads \
$(ATOMICS_TARGET_PAIRS) \
$(ATOMICS_BUILTINS_TARGET_PAIRS)
@@ -2144,9 +2118,7 @@ ifeq ($(strip $(filter-out darwin%,$(osys))),)
s-osinte.ads<s-osinte-darwin.ads \
s-taprop.adb<s-taprop-posix.adb \
s-taspri.ads<s-taspri-posix.ads \
- s-tpopsp.adb<s-tpopsp-posix-foreign.adb \
- g-trasym.ads<g-trasym-unimplemented.ads \
- g-trasym.adb<g-trasym-unimplemented.adb
+ s-tpopsp.adb<s-tpopsp-posix-foreign.adb
ifeq ($(strip $(filter-out %86,$(arch))),)
LIBGNAT_TARGET_PAIRS += \
@@ -2262,11 +2234,10 @@ LIBGNAT_OBJS = adadecode.o adaint.o argv.o cio.o cstreams.o ctrl_c.o \
include $(fsrcdir)/ada/Makefile.rtl
-GNATRTL_LINEARALGEBRA_OBJS = a-nlcoar.o a-nllcar.o \
- a-nucoar.o i-forbla.o i-forlap.o s-gearop.o
+GNATRTL_LINEARALGEBRA_OBJS = i-forbla.o i-forlap.o
GNATRTL_OBJS = $(GNATRTL_NONTASKING_OBJS) $(GNATRTL_TASKING_OBJS) \
- $(GNATRTL_LINEARALGEBRA_OBJS) g-trasym.o memtrack.o
+ $(GNATRTL_LINEARALGEBRA_OBJS) memtrack.o
# Default run time files
@@ -2446,7 +2417,6 @@ install-gnatlib: ../stamp-gnatlib-$(RTSDIR)
for file in $(RTSDIR)/*.ali; do \
$(INSTALL_DATA_DATE) $$file $(DESTDIR)$(ADA_RTL_OBJ_DIR); \
done
- -$(INSTALL_DATA) $(RTSDIR)/g-trasym$(objext) $(DESTDIR)$(ADA_RTL_OBJ_DIR)
-cd $(RTSDIR); for file in *$(arext);do \
$(INSTALL_DATA) $$file $(DESTDIR)$(ADA_RTL_OBJ_DIR); \
$(RANLIB_FOR_TARGET) $(DESTDIR)$(ADA_RTL_OBJ_DIR)/$$file; \
@@ -2766,10 +2736,6 @@ gnatlib-zcx:
THREAD_KIND="$(THREAD_KIND)" \
PICFLAG_FOR_TARGET="$(PICFLAG_FOR_TARGET)" gnatlib
-# .s files for cross-building
-gnat-cross: force
- make $(GNAT1_ADA_OBJS) CC="gcc -B../stage1/" CFLAGS="-S -gnatp"
-
# Compiling object files from source files.
# Note that dependencies on obstack.h are not written
@@ -2872,6 +2838,7 @@ mkdir.o : mkdir.c
socket.o : socket.c gsocket.h
sysdep.o : sysdep.c
raise.o : raise.c raise.h
+sigtramp-ppcvxw.o : sigtramp-ppcvxw.c sigtramp.h
vx_stack_info.o : vx_stack_info.c
raise-gcc.o : raise-gcc.c raise.h
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index d10fcf0ad92..c408de30296 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -355,6 +355,9 @@ do { \
/* Nonzero in a DECL if it is made for a pointer that can never be null. */
#define DECL_CAN_NEVER_BE_NULL_P(NODE) DECL_LANG_FLAG_2 (NODE)
+/* Nonzero in a VAR_DECL if it is made for a loop parameter. */
+#define DECL_LOOP_PARM_P(NODE) DECL_LANG_FLAG_3 (VAR_DECL_CHECK (NODE))
+
/* Nonzero in a FIELD_DECL that is a dummy built for some internal reason. */
#define DECL_INTERNAL_P(NODE) DECL_LANG_FLAG_3 (FIELD_DECL_CHECK (NODE))
@@ -409,9 +412,16 @@ do { \
|| (DECL_ORIGINAL_FIELD (FIELD1) \
&& (DECL_ORIGINAL_FIELD (FIELD1) == DECL_ORIGINAL_FIELD (FIELD2))))
-/* In a VAR_DECL, points to the object being renamed if the VAR_DECL is a
- renaming pointer, otherwise 0. Note that this object is guaranteed to
- be protected against multiple evaluations. */
+/* In a VAR_DECL with the DECL_LOOP_PARM_P flag set, points to the special
+ induction variable that is built under certain circumstances, if any. */
+#define DECL_INDUCTION_VAR(NODE) \
+ GET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))
+#define SET_DECL_INDUCTION_VAR(NODE, X) \
+ SET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE), X)
+
+/* In a VAR_DECL without the DECL_LOOP_PARM_P flag set and that is a renaming
+ pointer, points to the object being renamed, if any. Note that this object
+ is guaranteed to be protected against multiple evaluations. */
#define DECL_RENAMED_OBJECT(NODE) \
GET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))
#define SET_DECL_RENAMED_OBJECT(NODE, X) \
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 98d68fe01a6..81f891fee63 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -949,10 +949,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
if ((TREE_CODE (gnu_expr) == COMPONENT_REF
&& TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (gnu_expr, 0))))
/* Strip useless conversions around the object. */
- || (TREE_CODE (gnu_expr) == NOP_EXPR
- && gnat_types_compatible_p
- (TREE_TYPE (gnu_expr),
- TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))))
+ || gnat_useless_type_conversion (gnu_expr))
{
gnu_expr = TREE_OPERAND (gnu_expr, 0);
gnu_type = TREE_TYPE (gnu_expr);
@@ -1434,10 +1431,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TREE_ADDRESSABLE (gnu_decl) = 1;
}
+ /* If this is a loop parameter, set the corresponding flag. */
+ else if (kind == E_Loop_Parameter)
+ DECL_LOOP_PARM_P (gnu_decl) = 1;
+
/* If this is a renaming pointer, attach the renamed object to it and
register it if we are at the global level. Note that an external
constant is at the global level. */
- if (TREE_CODE (gnu_decl) == VAR_DECL && renamed_obj)
+ else if (TREE_CODE (gnu_decl) == VAR_DECL && renamed_obj)
{
SET_DECL_RENAMED_OBJECT (gnu_decl, renamed_obj);
if ((!definition && kind == E_Constant) || global_bindings_p ())
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 30fa99e96d5..143926160ac 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -450,8 +450,8 @@ extern void set_block_jmpbuf_decl (tree decl);
/* Get the setjmp_decl, if any, for the current binding level. */
extern tree get_block_jmpbuf_decl (void);
-/* Records a ..._DECL node DECL as belonging to the current lexical scope
- and uses GNAT_NODE for location information. */
+/* Record DECL as belonging to the current lexical scope and use GNAT_NODE
+ for location information and flag propagation. */
extern void gnat_pushdecl (tree decl, Node_Id gnat_node);
extern void gnat_init_gcc_eh (void);
@@ -479,6 +479,9 @@ extern tree gnat_signed_type (tree type_node);
transparently converted to each other. */
extern int gnat_types_compatible_p (tree t1, tree t2);
+/* Return true if EXPR is a useless type conversion. */
+extern bool gnat_useless_type_conversion (tree expr);
+
/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */
extern bool fntype_same_flags_p (const_tree, tree, bool, bool, bool);
@@ -489,6 +492,10 @@ extern bool fntype_same_flags_p (const_tree, tree, bool, bool, bool);
not permitted by the language being compiled. */
extern tree convert (tree type, tree expr);
+/* Create an expression whose value is that of EXPR converted to the common
+ index type, which is sizetype. */
+extern tree convert_to_index_type (tree expr);
+
/* Routines created solely for the tree translator's sake. Their prototypes
can be changed as desired. */
@@ -687,9 +694,12 @@ extern tree create_subprog_decl (tree subprog_name, tree asm_name,
appearing in the subprogram. */
extern void begin_subprog_body (tree subprog_decl);
-/* Finish the definition of the current subprogram BODY and finalize it. */
+/* Finish translating the current subprogram and set its BODY. */
extern void end_subprog_body (tree body);
+/* Wrap up compilation of SUBPROG_DECL, a subprogram body. */
+extern void rest_of_subprog_body_compilation (tree subprog_decl);
+
/* Build a template of type TEMPLATE_TYPE from the array bounds of ARRAY_TYPE.
EXPR is an expression that we can use to locate any PLACEHOLDER_EXPRs.
Return a constructor for the template. */
@@ -910,6 +920,11 @@ extern tree gnat_protect_expr (tree exp);
through something we don't know how to stabilize. */
extern tree gnat_stabilize_reference (tree ref, bool force, bool *success);
+/* If EXPR is an expression that is invariant in the current function, in the
+ sense that it can be evaluated anywhere in the function and any number of
+ times, return EXPR or an equivalent expression. Otherwise return NULL. */
+extern tree gnat_invariant_expr (tree expr);
+
/* Implementation of the builtin_function langhook. */
extern tree gnat_builtin_function (tree decl);
diff --git a/gcc/ada/gcc-interface/lang-specs.h b/gcc/ada/gcc-interface/lang-specs.h
index ff3de85b986..9657a6e5767 100644
--- a/gcc/ada/gcc-interface/lang-specs.h
+++ b/gcc/ada/gcc-interface/lang-specs.h
@@ -40,7 +40,7 @@
%{coverage:-fprofile-arcs -ftest-coverage} "
"%{gnatea:-gnatez} %{g*&m*} "
#if defined(TARGET_VXWORKS_RTP)
- "%{fRTS=rtp:-mrtp} "
+ "%{fRTS=rtp:-mrtp} %{fRTS=rtp-smp:-mrtp} %{fRTS=ravenscar-cert-rtp:-mrtp}"
#endif
"%1 %{!S:%{o*:%w%*-gnatO}} \
%i %{S:%W{o*}%{!o*:-o %b.s}} \
diff --git a/gcc/ada/gcc-interface/lang.opt b/gcc/ada/gcc-interface/lang.opt
index fd79c300112..48392352ebd 100644
--- a/gcc/ada/gcc-interface/lang.opt
+++ b/gcc/ada/gcc-interface/lang.opt
@@ -48,66 +48,35 @@ Ada AdaWhy Alias(nostdlib)
I
Ada AdaWhy Joined Separate
-; Documented for C
+-I <dir>. Add <dir> to the end of the main source path
Wall
Ada AdaWhy
-; Documented for C
-
-Wmissing-prototypes
-Ada AdaWhy
-; Documented for C
-
-Wstrict-prototypes
-Ada AdaWhy
-; Documented for C
-
-Wwrite-strings
-Ada AdaWhy
-; Documented for C
-
-Wlong-long
-Ada AdaWhy
-; Documented for C
-
-Wvariadic-macros
-Ada AdaWhy
-; Documented for C
-
-Wold-style-definition
-Ada AdaWhy
-; Documented for C
-
-Wmissing-format-attribute
-Ada AdaWhy
-; Documented for C
-
-Woverlength-strings
-Ada AdaWhy
-; Documented for C
+Enable most warning messages
k8
Driver
+Synonym of -gnatk8
nostdinc
Ada AdaWhy RejectNegative
-; Don't look for source files
+Do not look for source files in standard path
nostdlib
Ada AdaWhy
-; Don't look for object files
+Do not look for object files in standard path
fRTS=
Ada AdaWhy Joined RejectNegative
-; Selects the runtime
+Select the runtime
gant
Ada AdaWhy Joined Undocumented
-; Catches typos
+Catch typos
gnatO
Ada AdaWhy Separate
-; Sets name of output ALI file (internal switch)
+Set name of output ALI file (internal switch)
gnat
Ada AdaWhy Joined
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index f651af5afe3..a2de256b1dc 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -124,17 +124,6 @@ gnat_handle_option (size_t scode, const char *arg ATTRIBUTE_UNUSED, int value,
warn_maybe_uninitialized = value;
break;
- case OPT_Wmissing_prototypes:
- case OPT_Wstrict_prototypes:
- case OPT_Wwrite_strings:
- case OPT_Wlong_long:
- case OPT_Wvariadic_macros:
- case OPT_Wold_style_definition:
- case OPT_Wmissing_format_attribute:
- case OPT_Woverlength_strings:
- /* These are used in the GCC Makefile. */
- break;
-
case OPT_gant:
warning (0, "%<-gnat%> misspelled as %<-gant%>");
@@ -394,8 +383,12 @@ gnat_print_decl (FILE *file, tree node, int indent)
break;
case VAR_DECL:
- print_node (file, "renamed object", DECL_RENAMED_OBJECT (node),
- indent + 4);
+ if (DECL_LOOP_PARM_P (node))
+ print_node (file, "induction var", DECL_INDUCTION_VAR (node),
+ indent + 4);
+ else
+ print_node (file, "renamed object", DECL_RENAMED_OBJECT (node),
+ indent + 4);
break;
default:
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 71e659e265f..69c66d1b150 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -34,6 +34,8 @@
#include "libfuncs.h" /* For set_stack_check_libfunc. */
#include "tree-iterator.h"
#include "gimple.h"
+#include "bitmap.h"
+#include "cgraph.h"
#include "ada.h"
#include "adadecode.h"
@@ -125,11 +127,19 @@ DEF_VEC_ALLOC_P(parm_attr,gc);
struct GTY(()) language_function {
VEC(parm_attr,gc) *parm_attr_cache;
+ bitmap named_ret_val;
+ VEC(tree,gc) *other_ret_val;
};
#define f_parm_attr_cache \
DECL_STRUCT_FUNCTION (current_function_decl)->language->parm_attr_cache
+#define f_named_ret_val \
+ DECL_STRUCT_FUNCTION (current_function_decl)->language->named_ret_val
+
+#define f_other_ret_val \
+ DECL_STRUCT_FUNCTION (current_function_decl)->language->other_ret_val
+
/* A structure used to gather together information about a statement group.
We use this to gather related statements, for example the "then" part
of a IF. In the case where it represents a lexical scope, we may also
@@ -179,8 +189,33 @@ static GTY(()) VEC(tree,gc) *gnu_return_label_stack;
parameters. See processing for N_Subprogram_Body. */
static GTY(()) VEC(tree,gc) *gnu_return_var_stack;
-/* Stack of LOOP_STMT nodes. */
-static GTY(()) VEC(tree,gc) *gnu_loop_label_stack;
+/* Structure used to record information for a range check. */
+struct GTY(()) range_check_info_d {
+ tree low_bound;
+ tree high_bound;
+ tree type;
+ tree invariant_cond;
+};
+
+typedef struct range_check_info_d *range_check_info;
+
+DEF_VEC_P(range_check_info);
+DEF_VEC_ALLOC_P(range_check_info,gc);
+
+/* Structure used to record information for a loop. */
+struct GTY(()) loop_info_d {
+ tree label;
+ tree loop_var;
+ VEC(range_check_info,gc) *checks;
+};
+
+typedef struct loop_info_d *loop_info;
+
+DEF_VEC_P(loop_info);
+DEF_VEC_ALLOC_P(loop_info,gc);
+
+/* Stack of loop_info structures associated with LOOP_STMT nodes. */
+static GTY(()) VEC(loop_info,gc) *gnu_loop_stack;
/* The stacks for N_{Push,Pop}_*_Label. */
static GTY(()) VEC(tree,gc) *gnu_constraint_error_label_stack;
@@ -279,7 +314,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
(Get_Name_String (file_info_ptr[i].File_Name))));
/* We rely on the order isomorphism between files and line maps. */
- gcc_assert ((int) line_table->used == i);
+ gcc_assert ((int) LINEMAPS_ORDINARY_USED (line_table) == i);
/* We create the line map for a source file at once, with a fixed number
of columns chosen to avoid jumping over the next power of 2. */
@@ -626,6 +661,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
{
begin_subprog_body (info->elab_proc);
end_subprog_body (gnu_body);
+ rest_of_subprog_body_compilation (info->elab_proc);
}
}
@@ -997,6 +1033,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
if (TREE_CODE (gnu_result) == INDIRECT_REF)
TREE_THIS_NOTRAP (gnu_result) = 1;
+
+ if (read_only)
+ TREE_READONLY (gnu_result) = 1;
}
/* If it's a PARM_DECL to foreign convention subprogram, convert it. */
@@ -1013,6 +1052,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
we can reference the renamed object directly, since the renamed
expression has been protected against multiple evaluations. */
if (TREE_CODE (gnu_result) == VAR_DECL
+ && !DECL_LOOP_PARM_P (gnu_result)
&& DECL_RENAMED_OBJECT (gnu_result)
&& (!DECL_RENAMING_GLOBAL_P (gnu_result) || global_bindings_p ()))
gnu_result = DECL_RENAMED_OBJECT (gnu_result);
@@ -1324,10 +1364,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
don't try to build a trampoline. */
if (attribute == Attr_Code_Address)
{
- for (gnu_expr = gnu_result;
- CONVERT_EXPR_P (gnu_expr);
- gnu_expr = TREE_OPERAND (gnu_expr, 0))
- TREE_CONSTANT (gnu_expr) = 1;
+ gnu_expr = remove_conversions (gnu_result, false);
if (TREE_CODE (gnu_expr) == ADDR_EXPR)
TREE_NO_TRAMPOLINE (gnu_expr) = TREE_CONSTANT (gnu_expr) = 1;
@@ -1338,10 +1375,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
a useful warning with -Wtrampolines. */
else if (TREE_CODE (TREE_TYPE (gnu_prefix)) == FUNCTION_TYPE)
{
- for (gnu_expr = gnu_result;
- CONVERT_EXPR_P (gnu_expr);
- gnu_expr = TREE_OPERAND (gnu_expr, 0))
- ;
+ gnu_expr = remove_conversions (gnu_result, false);
if (TREE_CODE (gnu_expr) == ADDR_EXPR
&& decl_function_context (TREE_OPERAND (gnu_expr, 0)))
@@ -2103,6 +2137,43 @@ Case_Statement_to_gnu (Node_Id gnat_node)
return gnu_result;
}
+/* Find out whether VAR is an iteration variable of an enclosing loop in the
+ current function. If so, push a range_check_info structure onto the stack
+ of this enclosing loop and return it. Otherwise, return NULL. */
+
+static struct range_check_info_d *
+push_range_check_info (tree var)
+{
+ struct loop_info_d *iter = NULL;
+ unsigned int i;
+
+ if (VEC_empty (loop_info, gnu_loop_stack))
+ return NULL;
+
+ var = remove_conversions (var, false);
+
+ if (TREE_CODE (var) != VAR_DECL)
+ return NULL;
+
+ if (decl_function_context (var) != current_function_decl)
+ return NULL;
+
+ for (i = VEC_length (loop_info, gnu_loop_stack) - 1;
+ VEC_iterate (loop_info, gnu_loop_stack, i, iter);
+ i--)
+ if (var == iter->loop_var)
+ break;
+
+ if (iter)
+ {
+ struct range_check_info_d *rci = ggc_alloc_range_check_info_d ();
+ VEC_safe_push (range_check_info, gc, iter->checks, rci);
+ return rci;
+ }
+
+ return NULL;
+}
+
/* Return true if VAL (of type TYPE) can equal the minimum value if MAX is
false, or the maximum value if MAX is true, of TYPE. */
@@ -2170,10 +2241,15 @@ static tree
Loop_Statement_to_gnu (Node_Id gnat_node)
{
const Node_Id gnat_iter_scheme = Iteration_Scheme (gnat_node);
+ struct loop_info_d *gnu_loop_info = ggc_alloc_cleared_loop_info_d ();
tree gnu_loop_stmt = build4 (LOOP_STMT, void_type_node, NULL_TREE,
NULL_TREE, NULL_TREE, NULL_TREE);
tree gnu_loop_label = create_artificial_label (input_location);
- tree gnu_cond_expr = NULL_TREE, gnu_result;
+ tree gnu_cond_expr = NULL_TREE, gnu_low = NULL_TREE, gnu_high = NULL_TREE;
+ tree gnu_result;
+
+ /* Push the loop_info structure associated with the LOOP_STMT. */
+ VEC_safe_push (loop_info, gc, gnu_loop_stack, gnu_loop_info);
/* Set location information for statement and end label. */
set_expr_location_from_node (gnu_loop_stmt, gnat_node);
@@ -2181,9 +2257,8 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
&DECL_SOURCE_LOCATION (gnu_loop_label));
LOOP_STMT_LABEL (gnu_loop_stmt) = gnu_loop_label;
- /* Save the end label of this LOOP_STMT in a stack so that a corresponding
- N_Exit_Statement can find it. */
- VEC_safe_push (tree, gc, gnu_loop_label_stack, gnu_loop_label);
+ /* Save the label so that a corresponding N_Exit_Statement can find it. */
+ gnu_loop_info->label = gnu_loop_label;
/* Set the condition under which the loop must keep going.
For the case "LOOP .... END LOOP;" the condition is always true. */
@@ -2203,14 +2278,15 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
Entity_Id gnat_loop_var = Defining_Entity (gnat_loop_spec);
Entity_Id gnat_type = Etype (gnat_loop_var);
tree gnu_type = get_unpadded_type (gnat_type);
- tree gnu_low = TYPE_MIN_VALUE (gnu_type);
- tree gnu_high = TYPE_MAX_VALUE (gnu_type);
tree gnu_base_type = get_base_type (gnu_type);
tree gnu_one_node = convert (gnu_base_type, integer_one_node);
tree gnu_loop_var, gnu_loop_iv, gnu_first, gnu_last, gnu_stmt;
enum tree_code update_code, test_code, shift_code;
bool reverse = Reverse_Present (gnat_loop_spec), use_iv = false;
+ gnu_low = TYPE_MIN_VALUE (gnu_type);
+ gnu_high = TYPE_MAX_VALUE (gnu_type);
+
/* We must disable modulo reduction for the iteration variable, if any,
in order for the loop comparison to be effective. */
if (reverse)
@@ -2285,17 +2361,20 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
;
/* Otherwise, use the do-while form with the help of a special
- induction variable in the (unsigned version of) the base
- type, in order to have wrap-around arithmetics for it. */
+ induction variable in the unsigned version of the base type
+ or the unsigned version of the size type, whichever is the
+ largest, in order to have wrap-around arithmetics for it. */
else
{
- if (!TYPE_UNSIGNED (gnu_base_type))
- {
- gnu_base_type = gnat_unsigned_type (gnu_base_type);
- gnu_first = convert (gnu_base_type, gnu_first);
- gnu_last = convert (gnu_base_type, gnu_last);
- gnu_one_node = convert (gnu_base_type, integer_one_node);
- }
+ if (TYPE_PRECISION (gnu_base_type)
+ > TYPE_PRECISION (size_type_node))
+ gnu_base_type = gnat_unsigned_type (gnu_base_type);
+ else
+ gnu_base_type = size_type_node;
+
+ gnu_first = convert (gnu_base_type, gnu_first);
+ gnu_last = convert (gnu_base_type, gnu_last);
+ gnu_one_node = convert (gnu_base_type, integer_one_node);
use_iv = true;
}
@@ -2368,6 +2447,12 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
gnu_loop_var = gnat_to_gnu_entity (gnat_loop_var, gnu_first, 1);
if (DECL_BY_REF_P (gnu_loop_var))
gnu_loop_var = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_loop_var);
+ else if (use_iv)
+ {
+ gcc_assert (DECL_LOOP_PARM_P (gnu_loop_var));
+ SET_DECL_INDUCTION_VAR (gnu_loop_var, gnu_loop_iv);
+ }
+ gnu_loop_info->loop_var = gnu_loop_var;
/* Do all the arithmetics in the base type. */
gnu_loop_var = convert (gnu_base_type, gnu_loop_var);
@@ -2426,6 +2511,45 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
the LOOP_STMT to it, finish it and make it the "loop". */
if (Present (gnat_iter_scheme) && No (Condition (gnat_iter_scheme)))
{
+ struct range_check_info_d *rci;
+ unsigned n_checks = VEC_length (range_check_info, gnu_loop_info->checks);
+ unsigned int i;
+
+ /* First, if we have computed a small number of invariant conditions for
+ range checks applied to the iteration variable, then initialize these
+ conditions in front of the loop. Otherwise, leave them set to True.
+
+ ??? The heuristics need to be improved, by taking into account the
+ following datapoints:
+ - loop unswitching is disabled for big loops. The cap is the
+ parameter PARAM_MAX_UNSWITCH_INSNS (50).
+ - loop unswitching can only be applied a small number of times
+ to a given loop. The cap is PARAM_MAX_UNSWITCH_LEVEL (3).
+ - the front-end quickly generates useless or redundant checks
+ that can be entirely optimized away in the end. */
+ if (1 <= n_checks && n_checks <= 4)
+ for (i = 0;
+ VEC_iterate (range_check_info, gnu_loop_info->checks, i, rci);
+ i++)
+ {
+ tree low_ok
+ = build_binary_op (GE_EXPR, boolean_type_node,
+ convert (rci->type, gnu_low),
+ rci->low_bound);
+ tree high_ok
+ = build_binary_op (LE_EXPR, boolean_type_node,
+ convert (rci->type, gnu_high),
+ rci->high_bound);
+ tree range_ok
+ = build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
+ low_ok, high_ok);
+
+ TREE_OPERAND (rci->invariant_cond, 0)
+ = build_unary_op (TRUTH_NOT_EXPR, boolean_type_node, range_ok);
+
+ add_stmt_with_node_force (rci->invariant_cond, gnat_node);
+ }
+
add_stmt (gnu_loop_stmt);
gnat_poplevel ();
gnu_loop_stmt = end_stmt_group ();
@@ -2442,7 +2566,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
else
gnu_result = gnu_loop_stmt;
- VEC_pop (tree, gnu_loop_label_stack);
+ VEC_pop (loop_info, gnu_loop_stack);
return gnu_result;
}
@@ -2502,9 +2626,275 @@ establish_gnat_vms_condition_handler (void)
add_stmt (establish_stmt);
}
-/* Similar, but for RETURN_EXPR. If RET_VAL is non-null, build a RETURN_EXPR
- around the assignment of RET_VAL to RET_OBJ. Otherwise just build a bare
- RETURN_EXPR around RESULT_OBJ, which may be null in this case. */
+/* This page implements a form of Named Return Value optimization modelled
+ on the C++ optimization of the same name. The main difference is that
+ we disregard any semantical considerations when applying it here, the
+ counterpart being that we don't try to apply it to semantically loaded
+ return types, i.e. types with the TREE_ADDRESSABLE flag set.
+
+ We consider a function body of the following GENERIC form:
+
+ return_type R1;
+ [...]
+ RETURN_EXPR [<retval> = ...]
+ [...]
+ RETURN_EXPR [<retval> = R1]
+ [...]
+ return_type Ri;
+ [...]
+ RETURN_EXPR [<retval> = ...]
+ [...]
+ RETURN_EXPR [<retval> = Ri]
+ [...]
+
+ and we try to fulfill a simple criterion that would make it possible to
+ replace one or several Ri variables with the RESULT_DECL of the function.
+
+ The first observation is that RETURN_EXPRs that don't directly reference
+ any of the Ri variables on the RHS of their assignment are transparent wrt
+ the optimization. This is because the Ri variables aren't addressable so
+ any transformation applied to them doesn't affect the RHS; moreover, the
+ assignment writes the full <retval> object so existing values are entirely
+ discarded.
+
+ This property can be extended to some forms of RETURN_EXPRs that reference
+ the Ri variables, for example CONSTRUCTORs, but isn't true in the general
+ case, in particular when function calls are involved.
+
+ Therefore the algorithm is as follows:
+
+ 1. Collect the list of candidates for a Named Return Value (Ri variables
+ on the RHS of assignments of RETURN_EXPRs) as well as the list of the
+ other expressions on the RHS of such assignments.
+
+ 2. Prune the members of the first list (candidates) that are referenced
+ by a member of the second list (expressions).
+
+ 3. Extract a set of candidates with non-overlapping live ranges from the
+ first list. These are the Named Return Values.
+
+ 4. Adjust the relevant RETURN_EXPRs and replace the occurrences of the
+ Named Return Values in the function with the RESULT_DECL. */
+
+struct nrv_data
+{
+ bitmap nrv;
+ tree result;
+ struct pointer_set_t *visited;
+};
+
+/* Return true if T is a Named Return Value. */
+
+static inline bool
+is_nrv_p (bitmap nrv, tree t)
+{
+ return TREE_CODE (t) == VAR_DECL && bitmap_bit_p (nrv, DECL_UID (t));
+}
+
+/* Helper function for walk_tree, used by finalize_nrv below. */
+
+static tree
+prune_nrv_r (tree *tp, int *walk_subtrees, void *data)
+{
+ struct nrv_data *dp = (struct nrv_data *)data;
+ tree t = *tp;
+
+ /* No need to walk into types or decls. */
+ if (IS_TYPE_OR_DECL_P (t))
+ *walk_subtrees = 0;
+
+ if (is_nrv_p (dp->nrv, t))
+ bitmap_clear_bit (dp->nrv, DECL_UID (t));
+
+ return NULL_TREE;
+}
+
+/* Prune Named Return Values in BLOCK and return true if there is still a
+ Named Return Value in BLOCK or one of its sub-blocks. */
+
+static bool
+prune_nrv_in_block (bitmap nrv, tree block)
+{
+ bool has_nrv = false;
+ tree t;
+
+ /* First recurse on the sub-blocks. */
+ for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
+ has_nrv |= prune_nrv_in_block (nrv, t);
+
+ /* Then make sure to keep at most one NRV per block. */
+ for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
+ if (is_nrv_p (nrv, t))
+ {
+ if (has_nrv)
+ bitmap_clear_bit (nrv, DECL_UID (t));
+ else
+ has_nrv = true;
+ }
+
+ return has_nrv;
+}
+
+/* Helper function for walk_tree, used by finalize_nrv below. */
+
+static tree
+finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
+{
+ struct nrv_data *dp = (struct nrv_data *)data;
+ tree t = *tp;
+
+ /* No need to walk into types. */
+ if (TYPE_P (t))
+ *walk_subtrees = 0;
+
+ /* Change RETURN_EXPRs of NRVs to just refer to the RESULT_DECL; this is a
+ nop, but differs from using NULL_TREE in that it indicates that we care
+ about the value of the RESULT_DECL. */
+ else if (TREE_CODE (t) == RETURN_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR)
+ {
+ tree ret_val = TREE_OPERAND (TREE_OPERAND (t, 0), 1), init_expr;
+
+ /* If this is the temporary created for a return value with variable
+ size in call_to_gnu, we replace the RHS with the init expression. */
+ if (TREE_CODE (ret_val) == COMPOUND_EXPR
+ && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
+ && TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0)
+ == TREE_OPERAND (ret_val, 1))
+ {
+ init_expr = TREE_OPERAND (TREE_OPERAND (ret_val, 0), 1);
+ ret_val = TREE_OPERAND (ret_val, 1);
+ }
+ else
+ init_expr = NULL_TREE;
+
+ /* Strip useless conversions around the return value. */
+ if (gnat_useless_type_conversion (ret_val))
+ ret_val = TREE_OPERAND (ret_val, 0);
+
+ if (is_nrv_p (dp->nrv, ret_val))
+ {
+ if (init_expr)
+ TREE_OPERAND (TREE_OPERAND (t, 0), 1) = init_expr;
+ else
+ TREE_OPERAND (t, 0) = dp->result;
+ }
+ }
+
+ /* Replace the DECL_EXPR of NRVs with an initialization of the RESULT_DECL,
+ if needed. */
+ else if (TREE_CODE (t) == DECL_EXPR
+ && is_nrv_p (dp->nrv, DECL_EXPR_DECL (t)))
+ {
+ tree var = DECL_EXPR_DECL (t), init;
+
+ if (DECL_INITIAL (var))
+ {
+ init = build_binary_op (INIT_EXPR, NULL_TREE, dp->result,
+ DECL_INITIAL (var));
+ SET_EXPR_LOCATION (init, EXPR_LOCATION (t));
+ DECL_INITIAL (var) = NULL_TREE;
+ }
+ else
+ init = build_empty_stmt (EXPR_LOCATION (t));
+ *tp = init;
+
+ /* Identify the NRV to the RESULT_DECL for debugging purposes. */
+ SET_DECL_VALUE_EXPR (var, dp->result);
+ DECL_HAS_VALUE_EXPR_P (var) = 1;
+ /* ??? Kludge to avoid an assertion failure during inlining. */
+ DECL_SIZE (var) = bitsize_unit_node;
+ DECL_SIZE_UNIT (var) = size_one_node;
+ }
+
+ /* And replace all uses of NRVs with the RESULT_DECL. */
+ else if (is_nrv_p (dp->nrv, t))
+ *tp = convert (TREE_TYPE (t), dp->result);
+
+ /* Avoid walking into the same tree more than once. Unfortunately, we
+ can't just use walk_tree_without_duplicates because it would only call
+ us for the first occurrence of NRVs in the function body. */
+ if (pointer_set_insert (dp->visited, *tp))
+ *walk_subtrees = 0;
+
+ return NULL_TREE;
+}
+
+/* Finalize the Named Return Value optimization for FNDECL. The NRV bitmap
+ contains the candidates for Named Return Value and OTHER is a list of
+ the other return values. */
+
+static void
+finalize_nrv (tree fndecl, bitmap nrv, VEC(tree,gc) *other)
+{
+ struct cgraph_node *node;
+ struct nrv_data data;
+ unsigned int i;
+ tree iter;
+
+ /* We shouldn't be applying the optimization to return types that we aren't
+ allowed to manipulate freely. */
+ gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (TREE_TYPE (fndecl))));
+
+ /* Prune the candidates that are referenced by other return values. */
+ data.nrv = nrv;
+ data.result = NULL_TREE;
+ data.visited = NULL;
+ for (i = 0; VEC_iterate(tree, other, i, iter); i++)
+ walk_tree_without_duplicates (&iter, prune_nrv_r, &data);
+ if (bitmap_empty_p (nrv))
+ return;
+
+ /* Prune also the candidates that are referenced by nested functions. */
+ node = cgraph_get_create_node (fndecl);
+ for (node = node->nested; node; node = node->next_nested)
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), prune_nrv_r,
+ &data);
+ if (bitmap_empty_p (nrv))
+ return;
+
+ /* Extract a set of NRVs with non-overlapping live ranges. */
+ if (!prune_nrv_in_block (nrv, DECL_INITIAL (fndecl)))
+ return;
+
+ /* Adjust the relevant RETURN_EXPRs and replace the occurrences of NRVs. */
+ data.nrv = nrv;
+ data.result = DECL_RESULT (fndecl);
+ data.visited = pointer_set_create ();
+ walk_tree (&DECL_SAVED_TREE (fndecl), finalize_nrv_r, &data, NULL);
+ pointer_set_destroy (data.visited);
+}
+
+/* Return true if RET_VAL can be used as a Named Return Value for the
+ anonymous return object RET_OBJ. */
+
+static bool
+return_value_ok_for_nrv_p (tree ret_obj, tree ret_val)
+{
+ if (TREE_CODE (ret_val) != VAR_DECL)
+ return false;
+
+ if (TREE_THIS_VOLATILE (ret_val))
+ return false;
+
+ if (DECL_CONTEXT (ret_val) != current_function_decl)
+ return false;
+
+ if (TREE_STATIC (ret_val))
+ return false;
+
+ if (TREE_ADDRESSABLE (ret_val))
+ return false;
+
+ if (DECL_ALIGN (ret_val) > DECL_ALIGN (ret_obj))
+ return false;
+
+ return true;
+}
+
+/* Build a RETURN_EXPR. If RET_VAL is non-null, build a RETURN_EXPR around
+ the assignment of RET_VAL to RET_OBJ. Otherwise build a bare RETURN_EXPR
+ around RESULT_OBJ, which may be null in this case. */
static tree
build_return_expr (tree ret_obj, tree ret_val)
@@ -2533,6 +2923,41 @@ build_return_expr (tree ret_obj, tree ret_val)
ret_val = convert (operation_type, ret_val);
result_expr = build2 (MODIFY_EXPR, void_type_node, ret_obj, ret_val);
+
+ /* If the function returns an aggregate type, find out whether this is
+ a candidate for Named Return Value. If so, record it. Otherwise,
+ if this is an expression of some kind, record it elsewhere. */
+ if (optimize
+ && AGGREGATE_TYPE_P (operation_type)
+ && !TYPE_IS_FAT_POINTER_P (operation_type)
+ && aggregate_value_p (operation_type, current_function_decl))
+ {
+ /* Recognize the temporary created for a return value with variable
+ size in call_to_gnu. We want to eliminate it if possible. */
+ if (TREE_CODE (ret_val) == COMPOUND_EXPR
+ && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR
+ && TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0)
+ == TREE_OPERAND (ret_val, 1))
+ ret_val = TREE_OPERAND (ret_val, 1);
+
+ /* Strip useless conversions around the return value. */
+ if (gnat_useless_type_conversion (ret_val))
+ ret_val = TREE_OPERAND (ret_val, 0);
+
+ /* Now apply the test to the return value. */
+ if (return_value_ok_for_nrv_p (ret_obj, ret_val))
+ {
+ if (!f_named_ret_val)
+ f_named_ret_val = BITMAP_GGC_ALLOC ();
+ bitmap_set_bit (f_named_ret_val, DECL_UID (ret_val));
+ }
+
+ /* Note that we need not care about CONSTRUCTORs here, as they are
+ totally transparent given the read-compose-write semantics of
+ assignments from CONSTRUCTORs. */
+ else if (EXPR_P (ret_val))
+ VEC_safe_push (tree, gc, f_other_ret_val, ret_val);
+ }
}
else
result_expr = ret_obj;
@@ -2601,6 +3026,7 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog)
gnat_poplevel ();
end_subprog_body (end_stmt_group ());
+ rest_of_subprog_body_compilation (gnu_stub_decl);
}
/* Subroutine of gnat_to_gnu to process gnat_node, an N_Subprogram_Body. We
@@ -2855,6 +3281,18 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
if (gnu_return_var_elmt)
TREE_VALUE (gnu_return_var_elmt) = void_type_node;
+ /* If the function returns an aggregate type and we have candidates for
+ a Named Return Value, finalize the optimization. */
+ if (optimize && gnu_subprog_language->named_ret_val)
+ {
+ finalize_nrv (gnu_subprog_decl, gnu_subprog_language->named_ret_val,
+ gnu_subprog_language->other_ret_val);
+ gnu_subprog_language->named_ret_val = NULL;
+ gnu_subprog_language->other_ret_val = NULL;
+ }
+
+ rest_of_subprog_body_compilation (gnu_subprog_decl);
+
/* If there is a stub associated with the function, build it now. */
if (DECL_FUNCTION_STUB (gnu_subprog_decl))
build_function_stub (gnu_subprog_decl, gnat_subprog_id);
@@ -3518,10 +3956,16 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target)
else
return gnu_call;
- /* If we nevertheless need a value, make a COMPOUND_EXPR to return it. */
+ /* If we nevertheless need a value, make a COMPOUND_EXPR to return it.
+ But first simplify if we have only one statement in the list. */
if (returning_value)
- gnu_result
- = build_compound_expr (TREE_TYPE (gnu_call), gnu_result, gnu_call);
+ {
+ tree first = expr_first (gnu_result), last = expr_last (gnu_result);
+ if (first == last)
+ gnu_result = first;
+ gnu_result
+ = build_compound_expr (TREE_TYPE (gnu_call), gnu_result, gnu_call);
+ }
return gnu_result;
}
@@ -3899,7 +4343,7 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
time, and reuse it to feed the end_handler hook's argument at exit. */
gnu_current_exc_ptr
- = build_call_expr (built_in_decls [BUILT_IN_EH_POINTER],
+ = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER),
1, integer_zero_node);
prev_gnu_incoming_exc_ptr = gnu_incoming_exc_ptr;
gnu_incoming_exc_ptr = create_var_decl (get_identifier ("EXPTR"), NULL_TREE,
@@ -5189,7 +5633,7 @@ gnat_to_gnu (Node_Id gnat_node)
to_ptr = build_fold_addr_expr (to);
from_ptr = build_fold_addr_expr (from);
- t = implicit_built_in_decls[BUILT_IN_MEMMOVE];
+ t = builtin_decl_implicit (BUILT_IN_MEMMOVE);
gnu_result = build_call_expr (t, 3, to_ptr, from_ptr, size);
}
}
@@ -5257,7 +5701,7 @@ gnat_to_gnu (Node_Id gnat_node)
? gnat_to_gnu (Condition (gnat_node)) : NULL_TREE),
(Present (Name (gnat_node))
? get_gnu_tree (Entity (Name (gnat_node)))
- : VEC_last (tree, gnu_loop_label_stack)));
+ : VEC_last (loop_info, gnu_loop_stack)->label));
break;
case N_Return_Statement:
@@ -5688,7 +6132,7 @@ gnat_to_gnu (Node_Id gnat_node)
is modelled on the C front-end. */
if (!allows_reg)
{
- STRIP_NOPS (output);
+ output = remove_conversions (output, false);
if (TREE_CODE (output) == CONST_DECL
&& DECL_CONST_CORRESPONDING_VAR (output))
output = DECL_CONST_CORRESPONDING_VAR (output);
@@ -5716,7 +6160,7 @@ gnat_to_gnu (Node_Id gnat_node)
mark it addressable. */
if (!allows_reg && allows_mem)
{
- STRIP_NOPS (input);
+ input = remove_conversions (input, false);
if (TREE_CODE (input) == CONST_DECL
&& DECL_CONST_CORRESPONDING_VAR (input))
input = DECL_CONST_CORRESPONDING_VAR (input);
@@ -5843,7 +6287,11 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Raise_Storage_Error:
{
const int reason = UI_To_Int (Reason (gnat_node));
- const Node_Id cond = Condition (gnat_node);
+ const Node_Id gnat_cond = Condition (gnat_node);
+ const bool with_extra_info = Exception_Extra_Info
+ && !No_Exception_Handlers_Set ()
+ && !get_exception_label (kind);
+ tree gnu_cond = NULL_TREE;
if (type_annotate_only)
{
@@ -5853,43 +6301,66 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_result_type = get_unpadded_type (Etype (gnat_node));
- if (Exception_Extra_Info
- && !No_Exception_Handlers_Set ()
- && !get_exception_label (kind)
- && VOID_TYPE_P (gnu_result_type)
- && Present (cond))
- switch (reason)
- {
- case CE_Access_Check_Failed:
+ switch (reason)
+ {
+ case CE_Access_Check_Failed:
+ if (with_extra_info)
gnu_result = build_call_raise_column (reason, gnat_node);
- break;
+ break;
- case CE_Index_Check_Failed:
- case CE_Range_Check_Failed:
- case CE_Invalid_Data:
- if (Nkind (cond) == N_Op_Not
- && Nkind (Right_Opnd (cond)) == N_In
- && Nkind (Right_Opnd (Right_Opnd (cond))) == N_Range)
- {
- Node_Id op = Right_Opnd (cond); /* N_In node */
- Node_Id index = Left_Opnd (op);
- Node_Id range = Right_Opnd (op);
- Node_Id type = Etype (index);
- if (Is_Type (type)
- && Known_Esize (type)
- && UI_To_Int (Esize (type)) <= 32)
- gnu_result
- = build_call_raise_range (reason, gnat_node,
- gnat_to_gnu (index),
- gnat_to_gnu
- (Low_Bound (range)),
- gnat_to_gnu
- (High_Bound (range)));
- }
- break;
+ case CE_Index_Check_Failed:
+ case CE_Range_Check_Failed:
+ case CE_Invalid_Data:
+ if (Present (gnat_cond)
+ && Nkind (gnat_cond) == N_Op_Not
+ && Nkind (Right_Opnd (gnat_cond)) == N_In
+ && Nkind (Right_Opnd (Right_Opnd (gnat_cond))) == N_Range)
+ {
+ Node_Id gnat_index = Left_Opnd (Right_Opnd (gnat_cond));
+ Node_Id gnat_type = Etype (gnat_index);
+ Node_Id gnat_range = Right_Opnd (Right_Opnd (gnat_cond));
+ tree gnu_index = gnat_to_gnu (gnat_index);
+ tree gnu_low_bound = gnat_to_gnu (Low_Bound (gnat_range));
+ tree gnu_high_bound = gnat_to_gnu (High_Bound (gnat_range));
+ struct range_check_info_d *rci;
+
+ if (with_extra_info
+ && Known_Esize (gnat_type)
+ && UI_To_Int (Esize (gnat_type)) <= 32)
+ gnu_result
+ = build_call_raise_range (reason, gnat_node, gnu_index,
+ gnu_low_bound, gnu_high_bound);
+
+ /* If loop unswitching is enabled, we try to compute invariant
+ conditions for checks applied to iteration variables, i.e.
+ conditions that are both independent of the variable and
+ necessary in order for the check to fail in the course of
+ some iteration, and prepend them to the original condition
+ of the checks. This will make it possible later for the
+ loop unswitching pass to replace the loop with two loops,
+ one of which has the checks eliminated and the other has
+ the original checks reinstated, and a run time selection.
+ The former loop will be suitable for vectorization. */
+ if (flag_unswitch_loops
+ && (gnu_low_bound = gnat_invariant_expr (gnu_low_bound))
+ && (gnu_high_bound = gnat_invariant_expr (gnu_high_bound))
+ && (rci = push_range_check_info (gnu_index)))
+ {
+ rci->low_bound = gnu_low_bound;
+ rci->high_bound = gnu_high_bound;
+ rci->type = gnat_to_gnu_type (gnat_type);
+ rci->invariant_cond = build1 (SAVE_EXPR, boolean_type_node,
+ boolean_true_node);
+ gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
+ boolean_type_node,
+ rci->invariant_cond,
+ gnat_to_gnu (gnat_cond));
+ }
+ }
+ break;
- default:
- break;
+ default:
+ break;
}
if (gnu_result == error_mark_node)
@@ -5901,10 +6372,14 @@ gnat_to_gnu (Node_Id gnat_node)
the code for the call. Handle a condition, if there is one. */
if (VOID_TYPE_P (gnu_result_type))
{
- if (Present (cond))
- gnu_result
- = build3 (COND_EXPR, void_type_node, gnat_to_gnu (cond),
- gnu_result, alloc_stmt_list ());
+ if (Present (gnat_cond))
+ {
+ if (!gnu_cond)
+ gnu_cond = gnat_to_gnu (gnat_cond);
+ gnu_result
+ = build3 (COND_EXPR, void_type_node, gnu_cond, gnu_result,
+ alloc_stmt_list ());
+ }
}
else
gnu_result = build1 (NULL_EXPR, gnu_result_type, gnu_result);
@@ -7916,12 +8391,10 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus)
Source_File_Index file = Get_Source_File_Index (Sloc);
Logical_Line_Number line = Get_Logical_Line_Number (Sloc);
Column_Number column = Get_Column_Number (Sloc);
- struct line_map *map = &line_table->maps[file - 1];
+ struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, file - 1);
- /* Translate the location according to the line-map.h formula. */
- *locus = map->start_location
- + ((line - map->to_line) << map->column_bits)
- + (column & ((1 << map->column_bits) - 1));
+ /* Translate the location. */
+ *locus = linemap_position_for_line_and_column (map, line, column);
}
ref_filename
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index feae636dece..272c192dbee 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -200,6 +200,9 @@ static GTY(()) struct gnat_binding_level *current_binding_level;
/* A chain of gnat_binding_level structures awaiting reuse. */
static GTY((deletable)) struct gnat_binding_level *free_binding_level;
+/* The context to be used for global declarations. */
+static GTY(()) tree global_context;
+
/* An array of global declarations. */
static GTY(()) VEC(tree,gc) *global_decls;
@@ -497,15 +500,19 @@ gnat_zaplevel (void)
free_binding_level = level;
}
-/* Records a ..._DECL node DECL as belonging to the current lexical scope
- and uses GNAT_NODE for location information and propagating flags. */
+/* Record DECL as belonging to the current lexical scope and use GNAT_NODE
+ for location information and flag propagation. */
void
gnat_pushdecl (tree decl, Node_Id gnat_node)
{
- /* If this decl is public external or at toplevel, there is no context. */
+ /* If DECL is public external or at top level, it has global context. */
if ((TREE_PUBLIC (decl) && DECL_EXTERNAL (decl)) || global_bindings_p ())
- DECL_CONTEXT (decl) = 0;
+ {
+ if (!global_context)
+ global_context = build_translation_unit_decl (NULL_TREE);
+ DECL_CONTEXT (decl) = global_context;
+ }
else
{
DECL_CONTEXT (decl) = current_function_decl;
@@ -518,11 +525,12 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
DECL_STATIC_CHAIN (decl) = 1;
}
- TREE_NO_WARNING (decl) = (gnat_node == Empty || Warnings_Off (gnat_node));
+ TREE_NO_WARNING (decl) = (No (gnat_node) || Warnings_Off (gnat_node));
/* Set the location of DECL and emit a declaration for it. */
if (Present (gnat_node))
Sloc_to_locus (Sloc (gnat_node), &DECL_SOURCE_LOCATION (decl));
+
add_decl_expr (decl, gnat_node);
/* Put the declaration on the list. The list of declarations is in reverse
@@ -1139,11 +1147,11 @@ compute_related_constant (tree op0, tree op1)
static tree
split_plus (tree in, tree *pvar)
{
- /* Strip NOPS in order to ease the tree traversal and maximize the
- potential for constant or plus/minus discovery. We need to be careful
+ /* Strip conversions in order to ease the tree traversal and maximize the
+ potential for constant or plus/minus discovery. We need to be careful
to always return and set *pvar to bitsizetype trees, but it's worth
the effort. */
- STRIP_NOPS (in);
+ in = remove_conversions (in, false);
*pvar = convert (bitsizetype, in);
@@ -1763,7 +1771,7 @@ process_attributes (tree decl, struct attrib *attr_list)
void
record_global_renaming_pointer (tree decl)
{
- gcc_assert (DECL_RENAMED_OBJECT (decl));
+ gcc_assert (!DECL_LOOP_PARM_P (decl) && DECL_RENAMED_OBJECT (decl));
VEC_safe_push (tree, gc, global_renaming_pointers, decl);
}
@@ -1958,7 +1966,7 @@ begin_subprog_body (tree subprog_decl)
make_decl_rtl (subprog_decl);
}
-/* Finish the definition of the current subprogram BODY and finalize it. */
+/* Finish translating the current subprogram and set its BODY. */
void
end_subprog_body (tree body)
@@ -1982,8 +1990,14 @@ end_subprog_body (tree body)
DECL_SAVED_TREE (fndecl) = body;
- current_function_decl = DECL_CONTEXT (fndecl);
+ current_function_decl = decl_function_context (fndecl);
+}
+
+/* Wrap up compilation of SUBPROG_DECL, a subprogram body. */
+void
+rest_of_subprog_body_compilation (tree subprog_decl)
+{
/* We cannot track the location of errors past this point. */
error_gnat_node = Empty;
@@ -1992,15 +2006,15 @@ end_subprog_body (tree body)
return;
/* Dump functions before gimplification. */
- dump_function (TDI_original, fndecl);
+ dump_function (TDI_original, subprog_decl);
/* ??? This special handling of nested functions is probably obsolete. */
- if (!DECL_CONTEXT (fndecl))
- cgraph_finalize_function (fndecl, false);
+ if (!decl_function_context (subprog_decl))
+ cgraph_finalize_function (subprog_decl, false);
else
/* Register this function with cgraph just far enough to get it
added to our parent's nested function list. */
- (void) cgraph_get_create_node (fndecl);
+ (void) cgraph_get_create_node (subprog_decl);
}
tree
@@ -2194,6 +2208,20 @@ gnat_types_compatible_p (tree t1, tree t2)
return 0;
}
+/* Return true if EXPR is a useless type conversion. */
+
+bool
+gnat_useless_type_conversion (tree expr)
+{
+ if (CONVERT_EXPR_P (expr)
+ || TREE_CODE (expr) == VIEW_CONVERT_EXPR
+ || TREE_CODE (expr) == NON_LVALUE_EXPR)
+ return gnat_types_compatible_p (TREE_TYPE (expr),
+ TREE_TYPE (TREE_OPERAND (expr, 0)));
+
+ return false;
+}
+
/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */
bool
@@ -2260,7 +2288,9 @@ max_size (tree exp, bool max_p)
switch (TREE_CODE_LENGTH (code))
{
case 1:
- if (code == NON_LVALUE_EXPR)
+ if (code == SAVE_EXPR)
+ return exp;
+ else if (code == NON_LVALUE_EXPR)
return max_size (TREE_OPERAND (exp, 0), max_p);
else
return
@@ -2302,9 +2332,7 @@ max_size (tree exp, bool max_p)
}
case 3:
- if (code == SAVE_EXPR)
- return exp;
- else if (code == COND_EXPR)
+ if (code == COND_EXPR)
return fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
max_size (TREE_OPERAND (exp, 1), max_p),
max_size (TREE_OPERAND (exp, 2), max_p));
@@ -4219,6 +4247,92 @@ convert (tree type, tree expr)
gcc_unreachable ();
}
}
+
+/* Create an expression whose value is that of EXPR converted to the common
+ index type, which is sizetype. EXPR is supposed to be in the base type
+ of the GNAT index type. Calling it is equivalent to doing
+
+ convert (sizetype, expr)
+
+ but we try to distribute the type conversion with the knowledge that EXPR
+ cannot overflow in its type. This is a best-effort approach and we fall
+ back to the above expression as soon as difficulties are encountered.
+
+ This is necessary to overcome issues that arise when the GNAT base index
+ type and the GCC common index type (sizetype) don't have the same size,
+ which is quite frequent on 64-bit architectures. In this case, and if
+ the GNAT base index type is signed but the iteration type of the loop has
+ been forced to unsigned, the loop scalar evolution engine cannot compute
+ a simple evolution for the general induction variables associated with the
+ array indices, because it will preserve the wrap-around semantics in the
+ unsigned type of their "inner" part. As a result, many loop optimizations
+ are blocked.
+
+ The solution is to use a special (basic) induction variable that is at
+ least as large as sizetype, and to express the aforementioned general
+ induction variables in terms of this induction variable, eliminating
+ the problematic intermediate truncation to the GNAT base index type.
+ This is possible as long as the original expression doesn't overflow
+ and if the middle-end hasn't introduced artificial overflows in the
+ course of the various simplification it can make to the expression. */
+
+tree
+convert_to_index_type (tree expr)
+{
+ enum tree_code code = TREE_CODE (expr);
+ tree type = TREE_TYPE (expr);
+
+ /* If the type is unsigned, overflow is allowed so we cannot be sure that
+ EXPR doesn't overflow. Keep it simple if optimization is disabled. */
+ if (TYPE_UNSIGNED (type) || !optimize)
+ return convert (sizetype, expr);
+
+ switch (code)
+ {
+ case VAR_DECL:
+ /* The main effect of the function: replace a loop parameter with its
+ associated special induction variable. */
+ if (DECL_LOOP_PARM_P (expr) && DECL_INDUCTION_VAR (expr))
+ expr = DECL_INDUCTION_VAR (expr);
+ break;
+
+ CASE_CONVERT:
+ {
+ tree otype = TREE_TYPE (TREE_OPERAND (expr, 0));
+ /* Bail out as soon as we suspect some sort of type frobbing. */
+ if (TYPE_PRECISION (type) != TYPE_PRECISION (otype)
+ || TYPE_UNSIGNED (type) != TYPE_UNSIGNED (otype))
+ break;
+ }
+
+ /* ... fall through ... */
+
+ case NON_LVALUE_EXPR:
+ return fold_build1 (code, sizetype,
+ convert_to_index_type (TREE_OPERAND (expr, 0)));
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ return fold_build2 (code, sizetype,
+ convert_to_index_type (TREE_OPERAND (expr, 0)),
+ convert_to_index_type (TREE_OPERAND (expr, 1)));
+
+ case COMPOUND_EXPR:
+ return fold_build2 (code, sizetype, TREE_OPERAND (expr, 0),
+ convert_to_index_type (TREE_OPERAND (expr, 1)));
+
+ case COND_EXPR:
+ return fold_build3 (code, sizetype, TREE_OPERAND (expr, 0),
+ convert_to_index_type (TREE_OPERAND (expr, 1)),
+ convert_to_index_type (TREE_OPERAND (expr, 2)));
+
+ default:
+ break;
+ }
+
+ return convert (sizetype, expr);
+}
/* Remove all conversions that are done in EXP. This includes converting
from a padded type or to a justified modular type. If TRUE_ADDRESS
@@ -4245,8 +4359,9 @@ remove_conversions (tree exp, bool true_address)
return remove_conversions (TREE_OPERAND (exp, 0), true_address);
break;
- case VIEW_CONVERT_EXPR: case NON_LVALUE_EXPR:
CASE_CONVERT:
+ case VIEW_CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
return remove_conversions (TREE_OPERAND (exp, 0), true_address);
default:
@@ -5629,7 +5744,7 @@ def_builtin_1 (enum built_in_function fncode,
/* Preserve an already installed decl. It most likely was setup in advance
(e.g. as part of the internal builtins) for specific reasons. */
- if (built_in_decls[(int) fncode] != NULL_TREE)
+ if (builtin_decl_explicit (fncode) != NULL_TREE)
return;
gcc_assert ((!both_p && !fallback_p)
@@ -5646,9 +5761,7 @@ def_builtin_1 (enum built_in_function fncode,
add_builtin_function (libname, libtype, fncode, fnclass,
NULL, fnattrs);
- built_in_decls[(int) fncode] = decl;
- if (implicit_p)
- implicit_built_in_decls[(int) fncode] = decl;
+ set_builtin_decl (fncode, decl, implicit_p);
}
static int flag_isoc94 = 0;
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index cf290a397b1..10d12ef7ea3 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -798,7 +798,7 @@ build_binary_op (enum tree_code op_code, tree result_type,
/* Then convert the right operand to its base type. This will prevent
unneeded sign conversions when sizetype is wider than integer. */
right_operand = convert (right_base_type, right_operand);
- right_operand = convert (sizetype, right_operand);
+ right_operand = convert_to_index_type (right_operand);
modulus = NULL_TREE;
break;
@@ -1277,13 +1277,8 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
case INDIRECT_REF:
{
- bool can_never_be_null;
- tree t = operand;
-
- while (CONVERT_EXPR_P (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR)
- t = TREE_OPERAND (t, 0);
-
- can_never_be_null = DECL_P (t) && DECL_CAN_NEVER_BE_NULL_P (t);
+ tree t = remove_conversions (operand, false);
+ bool can_never_be_null = DECL_P (t) && DECL_CAN_NEVER_BE_NULL_P (t);
/* If TYPE is a thin pointer, first convert to the fat pointer. */
if (TYPE_IS_THIN_POINTER_P (type)
@@ -2598,3 +2593,85 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
return result;
}
+
+/* If EXPR is an expression that is invariant in the current function, in the
+ sense that it can be evaluated anywhere in the function and any number of
+ times, return EXPR or an equivalent expression. Otherwise return NULL. */
+
+tree
+gnat_invariant_expr (tree expr)
+{
+ tree type = TREE_TYPE (expr), t;
+
+ expr = remove_conversions (expr, false);
+
+ while ((TREE_CODE (expr) == CONST_DECL
+ || (TREE_CODE (expr) == VAR_DECL && TREE_READONLY (expr)))
+ && decl_function_context (expr) == current_function_decl
+ && DECL_INITIAL (expr))
+ expr = remove_conversions (DECL_INITIAL (expr), false);
+
+ if (TREE_CONSTANT (expr))
+ return fold_convert (type, expr);
+
+ t = expr;
+
+ while (true)
+ {
+ switch (TREE_CODE (t))
+ {
+ case COMPONENT_REF:
+ if (TREE_OPERAND (t, 2) != NULL_TREE)
+ return NULL_TREE;
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ if (!TREE_CONSTANT (TREE_OPERAND (t, 1))
+ || TREE_OPERAND (t, 2) != NULL_TREE
+ || TREE_OPERAND (t, 3) != NULL_TREE)
+ return NULL_TREE;
+ break;
+
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ break;
+
+ case INDIRECT_REF:
+ if (!TREE_READONLY (t)
+ || TREE_SIDE_EFFECTS (t)
+ || !TREE_THIS_NOTRAP (t))
+ return NULL_TREE;
+ break;
+
+ default:
+ goto object;
+ }
+
+ t = TREE_OPERAND (t, 0);
+ }
+
+object:
+ if (TREE_SIDE_EFFECTS (t))
+ return NULL_TREE;
+
+ if (TREE_CODE (t) == CONST_DECL
+ && (DECL_EXTERNAL (t)
+ || decl_function_context (t) != current_function_decl))
+ return fold_convert (type, expr);
+
+ if (!TREE_READONLY (t))
+ return NULL_TREE;
+
+ if (TREE_CODE (t) == PARM_DECL)
+ return fold_convert (type, expr);
+
+ if (TREE_CODE (t) == VAR_DECL
+ && (DECL_EXTERNAL (t)
+ || decl_function_context (t) != current_function_decl))
+ return fold_convert (type, expr);
+
+ return NULL_TREE;
+}
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 6d9138c7505..7e9b243b943 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -192,6 +192,7 @@ AdaCore@*
* Stack Related Facilities::
* Verifying Properties Using gnatcheck::
* Creating Sample Bodies Using gnatstub::
+* Creating Unit Tests Using gnattest::
* Generating Ada Bindings for C and C++ headers::
* Other Utility Programs::
* Running and Debugging Ada Programs::
@@ -468,6 +469,22 @@ Sample Bodies Using gnatstub
* Running gnatstub::
* Switches for gnatstub::
+Creating Unit Tests Using gnattest
+
+* Running gnattest::
+* Switches for gnattest::
+* Project Attributes for gnattest::
+* Simple Example::
+* Setting Up and Tearing Down Testing Environment::
+* Regenerating Tests::
+* Default Test Behavior::
+* Testing Primitive Operations of Tagged Types::
+* Test Inheritance::
+* Tagged Types Substitutability Testing::
+* Testing with Contracts::
+* Additional Tests::
+* Current Limitations::
+
Other Utility Programs
* Using Other Utility Programs with GNAT::
@@ -814,6 +831,10 @@ a utility that checks Ada code against a set of rules.
a utility that generates empty but compilable bodies for library units.
@item
+@ref{Creating Unit Tests Using gnattest}, discusses @code{gnattest},
+a utility that generates unit testing templates for library units.
+
+@item
@ref{Generating Ada Bindings for C and C++ headers}, describes how to
generate automatically Ada bindings from C and C++ headers.
@@ -13002,6 +13023,23 @@ Names are in lower case
@item ^-nM^/NAME_CASING=MIXED_CASE^
Names are in mixed case
+@cindex @option{^-ne@var{x}^/ENUM_CASING^} (@command{gnatpp})
+@item ^-neD^/ENUM_CASING=AS_DECLARED^
+Enumeration literal casing for defining occurrences are as they appear in the
+source file. Overrides ^-n^/NAME_CASING^ casing setting.
+
+@item ^-neU^/ENUM_CASING=UPPER_CASE^
+Enumeration literals are in upper case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
+@item ^-neL^/ENUM_CASING=LOWER_CASE^
+Enumeration literals are in lower case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
+@item ^-neM^/ENUM_CASING=MIXED_CASE^
+Enumeration literals are in mixed case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
@cindex @option{^-p@var{x}^/PRAGMA_CASING^} (@command{gnatpp})
@item ^-pL^/PRAGMA_CASING=LOWER_CASE^
Pragma names are lower case
@@ -17486,7 +17524,7 @@ current directory)
@item @samp{@var{gcc_switches}} is a list of switches for
@command{gcc}. They will be passed on to all compiler invocations made by
-@command{gnatelim} to generate the ASIS trees. Here you can provide
+@command{gnatstub} to generate the ASIS trees. Here you can provide
@option{^-I^/INCLUDE_DIRS=^} switches to form the source search path,
use the @option{-gnatec} switch to set the configuration file,
use the @option{-gnat05} switch if sources should be compiled in
@@ -17628,6 +17666,530 @@ Verbose mode: generate version information.
@end table
@c *********************************
+@node Creating Unit Tests Using gnattest
+@chapter Creating Unit Tests Using @command{gnattest}
+@findex gnattest
+
+@noindent
+@command{gnattest} is an ASIS-based utility that creates unit tests stubs
+as well as a test driver infrastructure (harness). @command{gnattest} creates
+a stub for each visible subprogram in the packages under consideration when
+they do not exist already.
+
+In order to process source files from the project, @command{gnattest} has to
+semantically analyze these Ada sources. Therefore, test stubs can only be
+generated for legal Ada units. If a unit is dependent on some other units,
+those units should be among source files of the project or of other projects
+imported by this one.
+
+Generated stubs and harness are based on the AUnit testing framework. AUnit is
+an Ada adaptation of the xxxUnit testing frameworks similar to JUnit for Java or
+CppUnit for C++. While it is advised that gnattest users read AUnit manual, deep
+knowledge of AUnit is not necessary for using gnattest. For correct operation of
+@command{gnattest} AUnit should be installed and aunit.gpr must be on the
+project path. This happens automatically when Aunit is installed at its default
+location.
+@menu
+* Running gnattest::
+* Switches for gnattest::
+* Project Attributes for gnattest::
+* Simple Example::
+* Setting Up and Tearing Down Testing Environment::
+* Regenerating Tests::
+* Default Test Behavior::
+* Testing Primitive Operations of Tagged Types::
+* Test Inheritance::
+* Tagged Types Substitutability Testing::
+* Testing with Contracts::
+* Additional Tests::
+* Current Limitations::
+@end menu
+
+@node Running gnattest
+@section Running @command{gnattest}
+
+@noindent
+@command{gnattest} has the command-line interface of the form
+
+@smallexample
+@c $ gnattest @var{-Pprojname} @ovar{switches} @ovar{filename} @ovar{directory}
+@c Expanding @ovar macro inline (explanation in macro def comments)
+$ gnattest @var{-Pprojname} @r{[}@var{--harness-dir=dirname}@r{]} @r{[}@var{switches}@r{]} @r{[}@var{filename}@r{]} @r{[}-cargs @var{gcc_switches}@r{]}
+@end smallexample
+
+@noindent
+where
+@table @var
+
+@item -Pprojname
+specifies the project that allow locating the source files. When no [filenames]
+are provided on the command line, all project sources are used as input. This
+switch is mandatory.
+
+@item --harness-dir=dirname
+specifies directory to put harness packages and project file for the test
+driver. The harness dir should be either specified by that switch or by
+corresponding attribute in the argument project file.
+
+@item filename
+is the name of the source file that contains a library unit package declaration
+for which a test package must be created. The file name may contain the path
+information.
+
+@item @samp{@var{gcc_switches}} is a list of switches for
+@command{gcc}. They will be passed on to all compiler invocations made by
+@command{gnatstub} to generate the ASIS trees. Here you can provide
+@option{^-I^/INCLUDE_DIRS=^} switches to form the source search path,
+use the @option{-gnatec} switch to set the configuration file,
+use the @option{-gnat05} switch if sources should be compiled in
+Ada 2005 mode etc.
+
+@item switches
+is an optional sequence of switches as described in the next section
+
+@end table
+
+@command{gnattest} results can be found in two different places.
+
+@itemize @bullet
+@item automatic harness
+the harnessing code which is located in the harness-dir as specified on the
+comand line or in the project file. All this code is generated completely
+automatically and can be destroyed and regenerated at will. It is not
+recommended to modify manually this code since it might be overridden
+easily. The entry point in this harnessing code is the project file called
+@command{test_driver.gpr}. Tests can be compiled and run using a command
+such as:
+
+@smallexample
+gnatmake -P<harness-dir>/test_driver
+test_runner
+@end smallexample
+
+@item actual unit test stubs
+a test stub for each visible subprogram is created in a separate file, if it
+doesn't exist already. By default, those separate test files are located in a
+"tests" directory that is created in the directory containing the source file
+itself. if it is not appropriate to create the tests in subdirs of the source,
+option @option{--separate-root} can be used. So let say for instance that
+a source file my_unit.ads in directory src contains a visible subprogram Proc.
+Then, the corresponding unit test will be found in file
+src/tests/my_unit-tests-proc_<code>.adb. <code> is an signature encoding used to
+differentiate test names in case of overloading.
+@end itemize
+
+@node Switches for gnattest
+@section Switches for @command{gnattest}
+
+@table @option
+@c !sort!
+
+@item --harness-only
+@cindex @option{--harness-only} (@command{gnattest})
+When this option is given, @command{gnattest} creates a harness for all
+sources treating them as test packages.
+
+@item --additional-tests=@var{projname}
+@cindex @option{--additional-tests} (@command{gnattest})
+Sources described in @var{projname} are considered potential additional
+manual tests to be added to the test suite.
+
+@item -r
+@cindex @option{-r} (@command{gnattest})
+Consider recursively all sources from all projects.
+
+@item -q
+@cindex @option{-q} (@command{gnattest})
+Supresses non-critical output messages.
+
+@item -v
+@cindex @option{-v} (@command{gnattest})
+Verbose mode: generate version information.
+
+@item --liskov
+@cindex @option{--liskov} (@command{gnattest})
+Enables Liskov verification: run all tests from all parents in order
+to check substitutability.
+
+@item --stub-default=@var{val}
+@cindex @option{--stub-default} (@command{gnattest})
+Specifies the default behavior of generated stubs. @var{val} can be either
+"fail" or "pass", "fail" being the default.
+
+@item --separate-root=@var{dirname}
+@cindex @option{--separate-root} (@command{gnattest})
+Directory hierarchy of tested sources is recreated in the @var{dirname} directory,
+test packages are placed in corresponding dirs.
+
+@item --subdir=@var{dirname}
+@cindex @option{--subdir} (@command{gnattest})
+Test packages are placed in subdirectories. That's the default output mode since
+it does not require any additional input from the user. Subdirs called "tests"
+will be created by default.
+
+@end table
+
+@option{--separate_root} and @option{--subdir} switches are mutually exclusive.
+
+@node Project Attributes for gnattest
+@section Project Attributes for @command{gnattest}
+
+@noindent
+
+Most of the command line options can be also given to the tool by adding
+special attributes to the project file. Those attributes should be put in
+package gnattest. Here is the list of the attributes.
+
+@itemize @bullet
+
+@item Separate_Stub_Root
+is used to select the same output mode as with the --separate-root option.
+This attribute cannot be used togather with Stub_Subdir.
+
+@item Stub_Subdir
+is used to select the same output mode as with the --sudbir option.
+This attribute cannot be used togather with Separate_Stub_Root.
+
+@item Harness_Dir
+is used to specify the directory to place harness packages and project
+file for the test driver, otherwise specified by --harness-dir.
+
+@item Additional_Tests
+is used to specify the project file otherwise given by
+--additional-tests switch.
+
+@item Stubs_Default
+is used to specify the default behaviour of test stubs, otherwise
+specified by --stub-default option. The value for this attribute
+shoul be either "pass" or "fail"
+
+@end itemize
+
+All those attributes can be overridden from command line if needed.
+Other @command{gnattest} switches can also be passed via the project
+file as an attribute list called GNATtest_Switches.
+
+@node Simple Example
+@section Simple Example
+
+@noindent
+
+Let's take a very simple example using the first @command{gnattest} example
+located at
+
+@smallexample
+<install_prefix>/share/examples/gnattest/simple
+@end smallexample
+
+This project contains a simple package containing one subprogram. By running gnattest
+
+@smallexample
+$ gnattest --harness-dir=driver -Psimple.gpr
+@end smallexample
+
+a test driver is created in dir "driver". It can be compiled and run:
+
+@smallexample
+$ cd driver
+$ gprbuild -Ptest_driver
+$ test_runner
+@end smallexample
+
+One failed test with diagnosis "test not implemented" is reported.
+Since no special output option was specified the test package Simple.Tests
+is located in
+
+@smallexample
+<install_prefix>/share/examples/gnattest/simple/src/tests
+@end smallexample
+
+For each package containing visible subprograms, a child test package is
+generated. It contains one test routine per tested subprogram. Each
+declaration of test subprogram has a comment specifying to which tested
+subprogram it corresponds. All the test routines have separated bodies.
+The test routine locates at simple-tests-test_inc_5eaee3.adb has a single
+statement - procedure Assert. It has two arguments: the boolean expression
+which we want to check and the diagnosis message to display if the condition
+is false.
+
+That is where actual testing code should be written after a proper setup.
+An actual check can be performed by replacing the assert statement with
+
+@smallexample @c ada
+Assert (Inc (1) = 2, "wrong incrementation");
+@end smallexample
+
+After recompiling and running the test driver one successfully passed test
+is reported.
+
+@node Setting Up and Tearing Down Testing Environment
+@section Setting Up and Tearing Down Testing Environment
+
+@noindent
+
+Besides test routines themselves, each test package has an inner package
+Env_Mgmt that has two procedures: User_Set_Up and User_Tear_Down.
+User_Set_Up is called before each test routine of the package and
+User_Tear_Down is called after each test routine. Those two procedures can
+be used to perform necessary initialization and finalization,
+memory allocation etc.
+
+@node Regenerating Tests
+@section Regenerating Tests
+
+@noindent
+
+Bodies of test routines and env_mgmt packages are never overridden after they
+have been created once. As long as the name of the subprogram, full expanded Ada
+names and order of its parameters are the same, the old test routine will
+fit in it's place and no test stub will be generated for this subprogram.
+
+This can be demonstrated with the previous example. By uncommenting declaration
+and body of function Dec in simple.ads and simple.adb, running
+@command{gnattest} on the project and then running the test driver:
+
+@smallexample
+gnattest --harness-dir=driver -Psimple.gpr
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+the old test is not replaced with a stub neither lost but a new test stub is
+created for function Dec.
+
+The only way for regenerating tests stubs is t oremove the previously created
+tests.
+
+@node Default Test Behavior
+@section Default Test Behavior
+
+@noindent
+
+Generated test driver can treat all unimplemented tests in two ways:
+either count them all as failed (this is usefull to see which tests are still
+left to implement) or as passed (to sort out unimplemented ones from those
+actually failing for a reason).
+
+Test driver accepts a switch to specify this behavior: --stub-default=val,
+where val is either "pass" or "fail" (exactly as for @command{gnattest}).
+
+The default behavior of the test driver is set with the same switch
+passed to gnattest when generating the test driver.
+
+Passing it to the driver generated on the first example
+
+@smallexample
+test_runner --stub-default=pass
+@end smallexample
+
+makes both tests pass, even the unimplemented one.
+
+@node Testing Primitive Operations of Tagged Types
+@section Testing Primitive Operations of Tagged Types
+
+@noindent
+
+Creating test stubs for primitive operations of tagged types have a number
+of features. Test routines for all primitives of a given tagged type are
+placed in a separate child package named after the tagged type (so if you
+have tagged type T in package P all tests for primitives of T will be in
+P.T_Tests).
+
+By running gnattest on the second example (actual tests for this example
+are already written so no need to worry if the tool reports that 0 new stubs
+were generated).
+
+@smallexample
+cd <install_prefix>/share/examples/gnattest/tagged_rec
+gnattest --harness-dir=driver -Ptagged_rec.gpr
+@end smallexample
+
+Taking a closer look at the test type declared in the test package
+Speed1.Controller_Tests is necessary. It is declared in
+
+@smallexample
+<install_prefix>/share/examples/gnattest/tagged_rec/src/tests
+@end smallexample
+
+Test types are direct or indirect descendants of
+AUnit.Test_Fixtures.Test_Fixture type. For non-primitive tested subprograms
+there is no need for the user to care about them. However when generating
+test packages for primitive operations, there are some things the user
+should know.
+
+Type Test_Controller has component that allows to assign it all kinds of
+derivations of type Controller. And if you look at the specification of
+package Speed2.Auto_Controller, you can see, that Test_Auto_Controller
+actually derives from Test_Controller rather that AUnit type Test_Fixture.
+Thus test types repeat the hierarchy of tested types.
+
+The User_Set_Up procedure of Env_Mgmt package corresponding to a test package
+of primitive operations of type T assigns Fixture with a reference to an
+object of that exact type T. Notice however, that if the tagged type has
+discriminants, the User_Set_Up only has a commented template of setting
+up the fixture since filling the discriminant with actual value is up
+to the user.
+
+The knowledge of the structure if test types allows to have additional testing
+without additional effort. Those possibilities are described below.
+
+@node Test Inheritance
+@section Test Inheritance
+
+@noindent
+
+Since test type hierarchy mimics the hierarchy of tested types, the
+inheritance of tests take place. An example of such inheritance can be
+shown by running the test driver generated for second example. As previously
+mentioned, actual tests are already written for this example.
+
+@smallexample
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+There are 6 passed tests while there are only 5 testable subprograms. Test
+routine for function Speed has been inherited and ran against objects of the
+derived type.
+
+@node Tagged Types Substitutability Testing
+@section Tagged Types Substitutability Testing
+
+@noindent
+
+Tagged Types Substitutability Testing is a way of verifying by testing
+the Liskov substitution principle (LSP). LSP is a principle stating that if
+S is a subtype of T (in Ada, S is a derived type of tagged type T),
+then objects of type T may be replaced with objects of type S (i.e., objects
+of type S may be substituted for objects of type T), without altering any of
+the desirable properties of the program. When the properties of the program are
+expressed in the form of subprogram pre & postconditions, LSP is formulated
+as relations between the pre & post of primitive operations and the pre & post
+of theirs derived operations. The pre of a derived operation should not be
+stronger that the original pre, and the post of the derived operation should not
+be weaker than the original post. Those relations insure that verifying if a
+dyspatching call is safe can be done just with the pre & post of the root
+operation.
+
+Verifying LSP by testing consists in running all the unit tests associated with
+the primitives of a given tagged type with objects of its derived types.
+
+In the example used by the previous section there clearly have a violation of LSP.
+The overriding primitive Adjust_Speed in package Speed2 removes the
+functionality of the overridden primitive and thus doesn't respect LSP.
+Gnattest has a special option to run
+overridden parent tests against objects of the type which have overriding
+primitives.
+
+@smallexample
+gnattest --harness-dir=driver --liskov -Ptagged_rec.gpr
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+While all the tests pass by themselves, the parent test for Adjust_Speed fails
+against object of derived type.
+
+@node Testing with Contracts
+@section Testing with Contracts
+
+@noindent
+
+@command{gnattest} supports pragmas Precondition, Postcondition and Test_Case.
+Test routines are generated one per each Test_Case associated with a tested
+subprogram. Those test routines have special wrappers for tested functions
+that have composition of pre- and postcondition of the subprogram an
+"requires" and "ensures" of the Test_Case (depending on the mode pre- and post
+either count for Nominal mode or do not for Robustness mode).
+
+The third example demonstrates how it works:
+
+@smallexample
+cd <install_prefix>/share/examples/gnattest/contracts
+gnattest --harness-dir=driver -Pcontracts.gpr
+@end smallexample
+
+Putting actual checks within the range of the contract does not cause any
+error reports. For example, for the test routine which corresponds to
+test case 1
+
+@smallexample @c ada
+Assert (Sqrt (9.0) = 3.0, "wrong sqrt");
+@end smallexample
+
+and for the test routine corresponding to test case 2
+
+@smallexample @c ada
+Assert (Sqrt (-5.0) = -1.0, "wrong error indication");
+@end smallexample
+
+are acceptable:
+
+@smallexample
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+However, by by changing 9.0 to 25.0 and 3.0 to 5.0 for example you can get
+a precondition violation for test case one. Also by putting any otherwise
+correct but positive pair of numbers to the second test routine you can also
+get a precondition violation. Postconditions are checked and reported
+the same way.
+
+@node Additional Tests
+@section Additional Tests
+
+@noindent
+@command{gnattest} can add user written tests to the main suite of the test
+driver. @command{gnattest} traverses given packages and searches for test
+routines. All procedures with a single in out parameter of a type which is
+a derivation of AUnit.Test_Fixtures.Test_Fixture declared in package
+specifications are added to the suites and then are executed by test driver.
+(Set_Up and Tear_Down are filtered out).
+
+An example illustrates two ways of crating test harness for user written tests.
+Directory additional contains a AUnit based test driver written by hand.
+
+@smallexample
+<install_prefix>/share/examples/gnattest/additional_tests/
+@end smallexample
+
+To create a test driver for already written tests use --harness-only option:
+
+@smallexample
+gnattest -Padditional/harness/harness.gpr --harness-dir=harness_only \
+ --harness-only
+gnatmake -Pharness_only/test_driver.gpr
+harness_only/test_runner
+@end smallexample
+
+Additional tests can also be executed together withgenerated tests:
+
+@smallexample
+gnattest -Psimple.gpr --additional-tests=additional/harness/harness.gpr \
+ --harness-dir=mixing
+gnatmake -Pmixing/test_driver.gpr
+mixing/test_runner
+@end smallexample
+
+@node Current Limitations
+@section Current Limitations
+
+@noindent
+
+The tool currently does not support following features:
+
+@itemize @bullet
+@item generic tests for generic packages and package instantiations
+@item tests for protected operations and entries
+@item acpects Pre-, Postcondition and Test_Case
+@end itemize
+
+@c *********************************
@node Generating Ada Bindings for C and C++ headers
@chapter Generating Ada Bindings for C and C++ headers
@findex binding
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index 61d3db3861f..9a1aab4c071 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -1614,7 +1614,9 @@ begin
-- Pass -mrtp to the linker if --RTS=rtp was passed
if Arg'Length > 8
- and then Arg (Arg'First + 6 .. Arg'First + 8) = "rtp"
+ and then
+ (Arg (Arg'First + 6 .. Arg'First + 8) = "rtp"
+ or else Arg (Arg'Last - 2 .. Arg'Last) = "rtp")
then
Linker_Options.Increment_Last;
Linker_Options.Table (Linker_Options.Last) :=
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index be1d05744f9..dfe176bf38d 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -61,7 +61,7 @@ package body Impunit is
-- The following is a giant string list containing the names of all non-
-- implementation internal files, i.e. the complete list of files for
-- internal units which a program may legitimately WITH when operating in
- -- either Ada 95 or Ada 05 mode.
+ -- either Ada 95 or Ada 2005 mode.
-- Note that this list should match the list of units documented in the
-- "GNAT Library" section of the GNAT Reference Manual. A unit listed here
diff --git a/gcc/ada/impunit.ads b/gcc/ada/impunit.ads
index e5244938ef9..be3e8d3c06a 100644
--- a/gcc/ada/impunit.ads
+++ b/gcc/ada/impunit.ads
@@ -25,8 +25,9 @@
-- This package contains data and functions used to determine if a given unit
-- is an internal unit intended only for use by the implementation and which
--- should not be directly WITH'ed by user code. It also checks for Ada 05
--- units that should only be WITH'ed in Ada 05 mode.
+-- should not be directly WITH'ed by user code. It also checks for Ada 2005
+-- units that should only be WITH'ed in Ada 2005 mode, and Ada 2012 units
+-- that should only be WITH'ed in Ada 2012 mode.
with Types; use Types;
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 0cf32e8166f..9ac475da3c5 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -1906,7 +1906,8 @@ __gnat_clear_exception_count (void)
/* Handle different SIGnal to exception mappings in different VxWorks
versions. */
static void
-__gnat_map_signal (int sig)
+__gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
+ struct sigcontext *sc ATTRIBUTE_UNUSED)
{
struct Exception_Data *exception;
const char *msg;
@@ -2001,9 +2002,7 @@ __gnat_map_signal (int sig)
propagation after the required low level adjustments. */
void
-__gnat_error_handler (int sig,
- void *si ATTRIBUTE_UNUSED,
- struct sigcontext *sc ATTRIBUTE_UNUSED)
+__gnat_error_handler (int sig, void *si, struct sigcontext *sc)
{
sigset_t mask;
@@ -2015,7 +2014,22 @@ __gnat_error_handler (int sig,
sigdelset (&mask, sig);
sigprocmask (SIG_SETMASK, &mask, NULL);
- __gnat_map_signal (sig);
+#if defined (__PPC__) && defined(_WRS_KERNEL)
+ /* On PowerPC, kernel mode, we process signals through a Call Frame Info
+ trampoline, voiding the need for myriads of fallback_frame_state
+ variants in the ZCX runtime. We have no simple way to distinguish ZCX
+ from SJLJ here, so we do this for SJLJ as well even though this is not
+ necessary. This only incurs a few extra instructions and a tiny
+ amount of extra stack usage. */
+
+ #include "sigtramp.h"
+
+ __gnat_sigtramp (sig, (void *)si, (void *)sc,
+ (sighandler_t *)&__gnat_map_signal);
+
+#else
+ __gnat_map_signal (sig, si, sc);
+#endif
}
void
diff --git a/gcc/ada/lib-xref.adb b/gcc/ada/lib-xref.adb
index 35cfdfca8a1..83a06e452f3 100644
--- a/gcc/ada/lib-xref.adb
+++ b/gcc/ada/lib-xref.adb
@@ -1910,7 +1910,9 @@ package body Lib.Xref is
Op := Ultimate_Alias (Old_E);
- -- Normal case of no alias present
+ -- Normal case of no alias present. We omit generated
+ -- primitives like tagged equality, that have no source
+ -- representation.
else
Op := Old_E;
@@ -1918,6 +1920,7 @@ package body Lib.Xref is
if Present (Op)
and then Sloc (Op) /= Standard_Location
+ and then Comes_From_Source (Op)
then
declare
Loc : constant Source_Ptr := Sloc (Op);
diff --git a/gcc/ada/link.c b/gcc/ada/link.c
index bf5d584b02b..8bcad27d86b 100644
--- a/gcc/ada/link.c
+++ b/gcc/ada/link.c
@@ -152,18 +152,6 @@ const char *__gnat_object_library_extension = ".a";
unsigned char __gnat_separate_run_path_options = 0;
const char *__gnat_default_libgcc_subdir = "lib";
-#elif defined (_AIX)
-const char *__gnat_object_file_option = "-Wl,-f,";
-const char *__gnat_run_path_option = "";
-int __gnat_link_max = 15000;
-const unsigned char __gnat_objlist_file_supported = 1;
-char __gnat_shared_libgnat_default = STATIC;
-char __gnat_shared_libgcc_default = STATIC;
-unsigned char __gnat_using_gnu_linker = 0;
-const char *__gnat_object_library_extension = ".a";
-unsigned char __gnat_separate_run_path_options = 0;
-const char *__gnat_default_libgcc_subdir = "lib";
-
#elif defined (__FreeBSD__)
const char *__gnat_object_file_option = "";
const char *__gnat_run_path_option = "-Wl,-rpath,";
@@ -204,12 +192,27 @@ const char *__gnat_default_libgcc_subdir = "lib64";
const char *__gnat_default_libgcc_subdir = "lib";
#endif
+#elif defined (_AIX)
+/* On AIX, even when with GNU ld we use native linker switches. This is
+ particularly important for '-f' as it should be interpreted by collect2. */
+
+const char *__gnat_object_file_option = "-Wl,-f,";
+const char *__gnat_run_path_option = "";
+char __gnat_shared_libgnat_default = STATIC;
+char __gnat_shared_libgcc_default = STATIC;
+int __gnat_link_max = 15000;
+const unsigned char __gnat_objlist_file_supported = 1;
+unsigned char __gnat_using_gnu_linker = 0;
+const char *__gnat_object_library_extension = ".a";
+unsigned char __gnat_separate_run_path_options = 0;
+const char *__gnat_default_libgcc_subdir = "lib";
+
#elif (HAVE_GNU_LD)
/* These are the settings for all systems that use gnu ld. GNU style response
file is supported, the shared library default is STATIC. */
-const char *__gnat_run_path_option = "";
const char *__gnat_object_file_option = "";
+const char *__gnat_run_path_option = "";
char __gnat_shared_libgnat_default = STATIC;
char __gnat_shared_libgcc_default = STATIC;
int __gnat_link_max = 8192;
diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb
index bf6a21a0dad..92043487bfa 100644
--- a/gcc/ada/make.adb
+++ b/gcc/ada/make.adb
@@ -4603,7 +4603,7 @@ package body Make is
procedure Library_Phase
(Stand_Alone_Libraries : in out Boolean;
- Library_Rebuilt : in out Boolean)
+ Library_Rebuilt : in out Boolean)
is
Depth : Natural;
Current : Natural;
diff --git a/gcc/ada/mlib-prj.adb b/gcc/ada/mlib-prj.adb
index 9020705d49b..83c74b94842 100644
--- a/gcc/ada/mlib-prj.adb
+++ b/gcc/ada/mlib-prj.adb
@@ -70,9 +70,6 @@ package body MLib.Prj is
S_Dec_Ads : File_Name_Type := No_File;
-- Name_Id for "dec.ads"
- G_Trasym_Ads : File_Name_Type := No_File;
- -- Name_Id for "g-trasym.ads"
-
Arguments : String_List_Access := No_Argument;
-- Used to accumulate arguments for the invocation of gnatbind and of the
-- compiler. Also used to collect the interface ALI when copying the ALI
@@ -316,9 +313,6 @@ package body MLib.Prj is
Libdecgnat_Needed : Boolean := False;
-- On OpenVMS, set True if library needs to be linked with libdecgnat
- Gtrasymobj_Needed : Boolean := False;
- -- On OpenVMS, set rue if library needs to be linked with g-trasym.obj
-
Object_Directory_Path : constant String :=
Get_Name_String
(For_Project.Object_Directory.Display_Name);
@@ -375,8 +369,7 @@ package body MLib.Prj is
-- to link with -lgnarl (this is the case when there is a dependency
-- on s-osinte.ads). On OpenVMS, set Libdecgnat_Needed if the ALI file
-- indicates that there is a need to link with -ldecgnat (this is the
- -- case when there is a dependency on dec.ads). Set Gtrasymobj_Needed
- -- if there is a dependency on g-trasym.ads.
+ -- case when there is a dependency on dec.ads).
procedure Process (The_ALI : File_Name_Type);
-- Check if the closure of a library unit which is or should be in the
@@ -513,8 +506,7 @@ package body MLib.Prj is
if Libgnarl_Needed /= Yes
or else
(Main_Project
- and then OpenVMS_On_Target
- and then ((not Libdecgnat_Needed) or (not Gtrasymobj_Needed)))
+ and then OpenVMS_On_Target)
then
-- Scan the ALI file
@@ -548,9 +540,6 @@ package body MLib.Prj is
elsif OpenVMS_On_Target then
if ALI.Sdep.Table (Index).Sfile = S_Dec_Ads then
Libdecgnat_Needed := True;
-
- elsif ALI.Sdep.Table (Index).Sfile = G_Trasym_Ads then
- Gtrasymobj_Needed := True;
end if;
end if;
end loop;
@@ -838,12 +827,6 @@ package body MLib.Prj is
S_Dec_Ads := Name_Find;
end if;
- if G_Trasym_Ads = No_File then
- Name_Len := 0;
- Add_Str_To_Name_Buffer ("g-trasym.ads");
- G_Trasym_Ads := Name_Find;
- end if;
-
-- We work in the object directory
Change_Dir (Object_Directory_Path);
@@ -1556,8 +1539,7 @@ package body MLib.Prj is
ALIs.Append (new String'(ALI_Path));
-- Find out if for this ALI file,
- -- libgnarl or libdecgnat or
- -- g-trasym.obj (on OpenVMS) is
+ -- libgnarl or libdecgnat is
-- necessary.
Check_Libs (ALI_Path, True);
@@ -1642,12 +1624,6 @@ package body MLib.Prj is
end if;
end if;
- if Gtrasymobj_Needed then
- Opts.Increment_Last;
- Opts.Table (Opts.Last) :=
- new String'(Lib_Directory & "/g-trasym.obj");
- end if;
-
if Libdecgnat_Needed then
Opts.Increment_Last;
diff --git a/gcc/ada/mlib-utl.adb b/gcc/ada/mlib-utl.adb
index 67e03097ed6..215fa5d6e8d 100644
--- a/gcc/ada/mlib-utl.adb
+++ b/gcc/ada/mlib-utl.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2002-2010, AdaCore --
+-- Copyright (C) 2002-2011, AdaCore --
-- --
-- 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- --
@@ -553,8 +553,7 @@ package body MLib.Utl is
Write_RF (Opening'Address, 1);
end if;
- Write_RF
- (Objects (J).all'Address, Objects (J).all'Length);
+ Write_RF (Objects (J).all'Address, Objects (J).all'Length);
-- Closing quote for GNU linker
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index 65a2d17b8e0..ed940d43c19 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -1638,11 +1638,11 @@ package Opt is
-- GNAT
-- This is the value of the configuration switch for the Ada 83 mode, as
-- set by the command line switches -gnat83/95/05, and possibly modified by
- -- the use of configuration pragmas Ada_83/Ada95/Ada05. This switch is used
- -- to set the initial value for Ada_Version mode at the start of analysis
- -- of a unit. Note however, that the setting of this flag is ignored for
- -- internal and predefined units (which are always compiled in the most up
- -- to date version of Ada).
+ -- the use of configuration pragmas Ada_*. This switch is used to set the
+ -- initial value for Ada_Version mode at the start of analysis of a unit.
+ -- Note however that the setting of this flag is ignored for internal and
+ -- predefined units (which are always compiled in the most up to date
+ -- version of Ada).
Ada_Version_Explicit_Config : Ada_Version_Type;
-- GNAT
diff --git a/gcc/ada/par-ch12.adb b/gcc/ada/par-ch12.adb
index b8b760cce4e..06261bc60b3 100644
--- a/gcc/ada/par-ch12.adb
+++ b/gcc/ada/par-ch12.adb
@@ -336,7 +336,7 @@ package body Ch12 is
begin
Generic_Assoc_Node := New_Node (N_Generic_Association, Token_Ptr);
- -- Ada2005: an association can be given by: others => <>
+ -- Ada 2005: an association can be given by: others => <>
if Token = Tok_Others then
if Ada_Version < Ada_2005 then
diff --git a/gcc/ada/par-ch2.adb b/gcc/ada/par-ch2.adb
index 67d52f67907..2cd54b7001c 100644
--- a/gcc/ada/par-ch2.adb
+++ b/gcc/ada/par-ch2.adb
@@ -59,33 +59,10 @@ package body Ch2 is
begin
-- All set if we do indeed have an identifier
- if Token = Tok_Identifier then
-
- -- Ada 2005 (AI-284): Compiling in Ada95 mode we warn that INTERFACE,
- -- OVERRIDING, and SYNCHRONIZED are new reserved words.
-
- if Ada_Version = Ada_95
- and then Warn_On_Ada_2005_Compatibility
- then
- if Token_Name = Name_Overriding
- or else Token_Name = Name_Synchronized
- or else (Token_Name = Name_Interface
- and then Prev_Token /= Tok_Pragma)
- then
- Error_Msg_N ("& is a reserved word in Ada 2005?", Token_Node);
- end if;
- end if;
-
- -- Similarly, warn about Ada 2012 reserved words
-
- if Ada_Version in Ada_95 .. Ada_2005
- and then Warn_On_Ada_2012_Compatibility
- then
- if Token_Name = Name_Some then
- Error_Msg_N ("& is a reserved word in Ada 2012?", Token_Node);
- end if;
- end if;
+ -- Code duplication, see Par_Ch3.P_Defining_Identifier???
+ if Token = Tok_Identifier then
+ Check_Future_Keyword;
Ident_Node := Token_Node;
Scan; -- past Identifier
return Ident_Node;
diff --git a/gcc/ada/par-ch3.adb b/gcc/ada/par-ch3.adb
index d58bce10451..ef017f08960 100644
--- a/gcc/ada/par-ch3.adb
+++ b/gcc/ada/par-ch3.adb
@@ -210,34 +210,10 @@ package body Ch3 is
-- we set Force_Msg to True, since we want at least one message for each
-- separate declaration (but not use) of a reserved identifier.
- if Token = Tok_Identifier then
-
- -- Ada 2005 (AI-284): Compiling in Ada95 mode we warn that INTERFACE,
- -- OVERRIDING, and SYNCHRONIZED are new reserved words. Note that
- -- in the case where these keywords are misused in Ada 95 mode,
- -- this routine will generally not be called at all.
+ -- Duplication should be removed, common code should be factored???
- if Ada_Version = Ada_95
- and then Warn_On_Ada_2005_Compatibility
- then
- if Token_Name = Name_Overriding
- or else Token_Name = Name_Synchronized
- or else (Token_Name = Name_Interface
- and then Prev_Token /= Tok_Pragma)
- then
- Error_Msg_N ("& is a reserved word in Ada 2005?", Token_Node);
- end if;
- end if;
-
- -- Similarly, warn about Ada 2012 reserved words
-
- if Ada_Version in Ada_95 .. Ada_2005
- and then Warn_On_Ada_2012_Compatibility
- then
- if Token_Name = Name_Some then
- Error_Msg_N ("& is a reserved word in Ada 2012?", Token_Node);
- end if;
- end if;
+ if Token = Tok_Identifier then
+ Check_Future_Keyword;
-- If we have a reserved identifier, manufacture an identifier with
-- a corresponding name after posting an appropriate error message
@@ -657,7 +633,7 @@ package body Ch3 is
Error_Msg_SP
("(Ada 83) limited record declaration not allowed!");
- -- In Ada2005, "abstract limited" can appear before "new",
+ -- In Ada 2005, "abstract limited" can appear before "new",
-- but it cannot be part of an untagged record declaration.
elsif Abstract_Present
@@ -4236,7 +4212,7 @@ package body Ch3 is
P_Identifier_Declarations (Decls, Done, In_Spec);
end if;
- -- Ada2005: A subprogram declaration can start with "not" or
+ -- Ada 2005: A subprogram declaration can start with "not" or
-- "overriding". In older versions, "overriding" is handled
-- like an identifier, with the appropriate messages.
diff --git a/gcc/ada/par-ch5.adb b/gcc/ada/par-ch5.adb
index fcfb428d1f8..e86f01c9155 100644
--- a/gcc/ada/par-ch5.adb
+++ b/gcc/ada/par-ch5.adb
@@ -1649,7 +1649,7 @@ package body Ch5 is
if Token = Tok_Of or else Token = Tok_Colon then
if Ada_Version < Ada_2012 then
- Error_Msg_SC ("iterator is an Ada2012 feature");
+ Error_Msg_SC ("iterator is an Ada 2012 feature");
end if;
return P_Iterator_Specification (ID_Node);
diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb
index 7b200e761b2..7d598547911 100644
--- a/gcc/ada/par-ch6.adb
+++ b/gcc/ada/par-ch6.adb
@@ -184,7 +184,7 @@ package body Ch6 is
Scope.Table (Scope.Last).Ecol := Start_Column;
Scope.Table (Scope.Last).Lreq := False;
- -- Ada2005: scan leading NOT OVERRIDING indicator
+ -- Ada 2005: Scan leading NOT OVERRIDING indicator
if Token = Tok_Not then
Scan; -- past NOT
@@ -1341,7 +1341,7 @@ package body Ch6 is
if Token = Tok_Aliased then
if Ada_Version < Ada_2012 then
- Error_Msg_SC ("ALIASED parameter is an Ada2012 feature");
+ Error_Msg_SC ("ALIASED parameter is an Ada 2012 feature");
else
Set_Aliased_Present (Specification_Node);
end if;
@@ -1677,6 +1677,14 @@ package body Ch6 is
Scan; -- past ALIASED
Set_Aliased_Present (Decl_Node);
+ if Ada_Version < Ada_2012 then
+ Error_Msg_SC -- CODEFIX
+ ("ALIASED not allowed in extended return in Ada2012?");
+ else
+ Error_Msg_SC -- CODEFIX
+ ("ALIASED not allowed in extended return");
+ end if;
+
if Token = Tok_Constant then
Scan; -- past CONSTANT
Set_Constant_Present (Decl_Node);
diff --git a/gcc/ada/par-util.adb b/gcc/ada/par-util.adb
index 6a0e8efc6cb..259cfb8e789 100644
--- a/gcc/ada/par-util.adb
+++ b/gcc/ada/par-util.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, 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- --
@@ -169,6 +169,43 @@ package body Util is
end Check_Bad_Layout;
--------------------------
+ -- Check_Future_Keyword --
+ --------------------------
+
+ procedure Check_Future_Keyword is
+ begin
+ -- Ada 2005 (AI-284): Compiling in Ada95 mode we warn that INTERFACE,
+ -- OVERRIDING, and SYNCHRONIZED are new reserved words.
+
+ if Ada_Version = Ada_95
+ and then Warn_On_Ada_2005_Compatibility
+ then
+ if Token_Name = Name_Overriding
+ or else Token_Name = Name_Synchronized
+ or else (Token_Name = Name_Interface
+ and then Prev_Token /= Tok_Pragma)
+ then
+ Error_Msg_N ("& is a reserved word in Ada 2005?", Token_Node);
+ end if;
+ end if;
+
+ -- Similarly, warn about Ada 2012 reserved words
+
+ if Ada_Version in Ada_95 .. Ada_2005
+ and then Warn_On_Ada_2012_Compatibility
+ then
+ if Token_Name = Name_Some then
+ Error_Msg_N ("& is a reserved word in Ada 2012?", Token_Node);
+ end if;
+ end if;
+
+ -- Note: we deliberately do not emit these warnings when operating in
+ -- Ada 83 mode because in that case we assume the user is building
+ -- legacy code anyway and is not interested in updating Ada versions.
+
+ end Check_Future_Keyword;
+
+ --------------------------
-- Check_Misspelling_Of --
--------------------------
diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb
index e054c198143..ed2e72473e6 100644
--- a/gcc/ada/par.adb
+++ b/gcc/ada/par.adb
@@ -1156,6 +1156,11 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is
-- mode. The caller has typically checked that the current token,
-- an identifier, matches one of the 95 keywords.
+ procedure Check_Future_Keyword;
+ -- Emit a warning if the current token is a valid identifier in the
+ -- language version in use, but is a reserved word in a later language
+ -- version (unless the language version in use is Ada 83).
+
procedure Check_Simple_Expression (E : Node_Id);
-- Given an expression E, that has just been scanned, so that Expr_Form
-- is still set, outputs an error if E is a non-simple expression. E is
diff --git a/gcc/ada/prj-conf.adb b/gcc/ada/prj-conf.adb
index 1514107effb..db8dba4ae88 100644
--- a/gcc/ada/prj-conf.adb
+++ b/gcc/ada/prj-conf.adb
@@ -1324,6 +1324,7 @@ package body Prj.Conf is
Prj.Proc.Process_Project_Tree_Phase_1
(In_Tree => Project_Tree,
Project => Config,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => Config_Project_Node,
From_Project_Node_Tree => Project_Node_Tree,
@@ -1465,6 +1466,7 @@ package body Prj.Conf is
Process_Project_Tree_Phase_1
(In_Tree => Project_Tree,
Project => Main_Project,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => User_Project_Node,
From_Project_Node_Tree => Project_Node_Tree,
diff --git a/gcc/ada/prj-pars.adb b/gcc/ada/prj-pars.adb
index f2d289f5c38..b76a77f1066 100644
--- a/gcc/ada/prj-pars.adb
+++ b/gcc/ada/prj-pars.adb
@@ -43,7 +43,7 @@ package body Prj.Pars is
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
Project_File_Name : String;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Reset_Tree : Boolean := True;
In_Node_Tree : Prj.Tree.Project_Node_Tree_Ref := null;
Env : in out Prj.Tree.Environment)
diff --git a/gcc/ada/prj-pars.ads b/gcc/ada/prj-pars.ads
index fb424a90033..23f3347d700 100644
--- a/gcc/ada/prj-pars.ads
+++ b/gcc/ada/prj-pars.ads
@@ -36,7 +36,7 @@ package Prj.Pars is
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
Project_File_Name : String;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Reset_Tree : Boolean := True;
In_Node_Tree : Prj.Tree.Project_Node_Tree_Ref := null;
Env : in out Prj.Tree.Environment);
diff --git a/gcc/ada/prj-part.adb b/gcc/ada/prj-part.adb
index 1c18680fbe8..022efe3c80b 100644
--- a/gcc/ada/prj-part.adb
+++ b/gcc/ada/prj-part.adb
@@ -443,7 +443,7 @@ package body Prj.Part is
Project : out Project_Node_Id;
Project_File_Name : String;
Errout_Handling : Errout_Mode := Always_Finalize;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Store_Comments : Boolean := False;
Current_Directory : String := "";
Is_Config_File : Boolean;
diff --git a/gcc/ada/prj-part.ads b/gcc/ada/prj-part.ads
index 1184c77a08d..708142ddb27 100644
--- a/gcc/ada/prj-part.ads
+++ b/gcc/ada/prj-part.ads
@@ -42,7 +42,7 @@ package Prj.Part is
Project : out Project_Node_Id;
Project_File_Name : String;
Errout_Handling : Errout_Mode := Always_Finalize;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Store_Comments : Boolean := False;
Current_Directory : String := "";
Is_Config_File : Boolean;
diff --git a/gcc/ada/prj-proc.adb b/gcc/ada/prj-proc.adb
index 269bc4552db..a46ee23bb36 100644
--- a/gcc/ada/prj-proc.adb
+++ b/gcc/ada/prj-proc.adb
@@ -145,6 +145,7 @@ package body Prj.Proc is
procedure Recursive_Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
Env : in out Prj.Tree.Environment;
@@ -1347,6 +1348,7 @@ package body Prj.Proc is
procedure Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
@@ -1361,6 +1363,7 @@ package body Prj.Proc is
From_Project_Node => From_Project_Node,
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
+ Packages_To_Check => Packages_To_Check,
Reset_Tree => Reset_Tree);
if Project_Qualifier_Of
@@ -2325,6 +2328,7 @@ package body Prj.Proc is
procedure Process_Project_Tree_Phase_1
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
@@ -2349,6 +2353,7 @@ package body Prj.Proc is
Recursive_Process
(Project => Project,
In_Tree => In_Tree,
+ Packages_To_Check => Packages_To_Check,
From_Project_Node => From_Project_Node,
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
@@ -2482,6 +2487,7 @@ package body Prj.Proc is
procedure Recursive_Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
Env : in out Prj.Tree.Environment;
@@ -2539,9 +2545,9 @@ package body Prj.Proc is
Recursive_Process
(In_Tree => In_Tree,
Project => New_Project,
+ Packages_To_Check => Packages_To_Check,
From_Project_Node =>
- Project_Node_Of
- (With_Clause, From_Project_Node_Tree),
+ Project_Node_Of (With_Clause, From_Project_Node_Tree),
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
Extended_By => No_Project);
@@ -2596,6 +2602,7 @@ package body Prj.Proc is
Prj.Part.Parse
(In_Tree => From_Project_Node_Tree,
Project => Loaded_Project,
+ Packages_To_Check => Packages_To_Check,
Project_File_Name => Get_Name_String (List.Path),
Errout_Handling => Prj.Part.Never_Finalize,
Current_Directory => Get_Name_String (Project.Directory.Name),
@@ -2627,6 +2634,7 @@ package body Prj.Proc is
Process_Project_Tree_Phase_1
(In_Tree => Tree,
Project => List.Project,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => Loaded_Project,
From_Project_Node_Tree => From_Project_Node_Tree,
@@ -2638,6 +2646,7 @@ package body Prj.Proc is
Process_Project_Tree_Phase_1
(In_Tree => Tree,
Project => List.Project,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => Loaded_Project,
From_Project_Node_Tree => From_Project_Node_Tree,
@@ -2859,8 +2868,10 @@ package body Prj.Proc is
Recursive_Process
(In_Tree => In_Tree,
Project => Project.Extends,
- From_Project_Node => Extended_Project_Of
- (Declaration_Node, From_Project_Node_Tree),
+ Packages_To_Check => Packages_To_Check,
+ From_Project_Node =>
+ Extended_Project_Of
+ (Declaration_Node, From_Project_Node_Tree),
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
Extended_By => Project);
diff --git a/gcc/ada/prj-proc.ads b/gcc/ada/prj-proc.ads
index f7fb7ad1411..72ab7eb919d 100644
--- a/gcc/ada/prj-proc.ads
+++ b/gcc/ada/prj-proc.ads
@@ -34,6 +34,7 @@ package Prj.Proc is
procedure Process_Project_Tree_Phase_1
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
@@ -68,6 +69,7 @@ package Prj.Proc is
procedure Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
diff --git a/gcc/ada/projects.texi b/gcc/ada/projects.texi
index 87627a26f72..356104f07c0 100644
--- a/gcc/ada/projects.texi
+++ b/gcc/ada/projects.texi
@@ -580,19 +580,19 @@ packages would be involved in the build process.
@b{for} Object_Dir @b{use} "obj";
@b{for} Exec_Dir @b{use} ".";
@b{for} Main @b{use} ("proc.adb");
- @b{end} Build;
- @b{package} Builder @b{is} --<<< for gnatmake and gprbuild
- @b{end} Builder;
+ @b{package} Builder @b{is} --<<< for gnatmake and gprbuild
+ @b{end} Builder;
- @b{package} Compiler @b{is} --<<< for the compiler
- @b{end} Compiler;
+ @b{package} Compiler @b{is} --<<< for the compiler
+ @b{end} Compiler;
- @b{package} Binder @b{is} --<<< for the binder
- @b{end} Binder;
+ @b{package} Binder @b{is} --<<< for the binder
+ @b{end} Binder;
- @b{package} Linker @b{is} --<<< for the linker
- @b{end} Linker;
+ @b{package} Linker @b{is} --<<< for the linker
+ @b{end} Linker;
+ @b{end} Build;
@end smallexample
@noindent
@@ -2015,8 +2015,16 @@ end Work;
@end smallexample
@noindent
-An extending project retains all the switches specified in the
-extended project.
+All packages that are not declared in the extending project are inherited from
+the project being extended, with their attributes, with the exception of
+@code{Linker'Linker_Options} which is never inherited. In particular, an
+extending project retains all the switches specified in the project being
+extended.
+
+At the project level, if they are not declared in the extending project, some
+attributes are inherited from the project being extended. They are:
+@code{Languages}, @code{Main} (for a root non library project) and
+@code{Library_Name} (for a project extending a library project)
@menu
* Project Hierarchy Extension::
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 07bf0121a56..b7a02066b77 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -1349,6 +1349,7 @@ package Rtsfind is
RE_Allocate_Any, -- System.Storage_Pools
RE_Deallocate_Any, -- System.Storage_Pools
RE_Root_Storage_Pool, -- System.Storage_Pools
+ RE_Root_Storage_Pool_Ptr, -- System.Storage_Pools
RE_Allocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools
@@ -2545,6 +2546,7 @@ package Rtsfind is
RE_Allocate_Any => System_Storage_Pools,
RE_Deallocate_Any => System_Storage_Pools,
RE_Root_Storage_Pool => System_Storage_Pools,
+ RE_Root_Storage_Pool_Ptr => System_Storage_Pools,
RE_Allocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools,
diff --git a/gcc/ada/s-gearop.adb b/gcc/ada/s-gearop.adb
index cb07f40902e..58602e1e0a8 100644
--- a/gcc/ada/s-gearop.adb
+++ b/gcc/ada/s-gearop.adb
@@ -29,6 +29,8 @@
-- --
------------------------------------------------------------------------------
+with Ada.Numerics; use Ada.Numerics;
+
package body System.Generic_Array_Operations is
-- The local function Check_Unit_Last computes the index
@@ -109,7 +111,8 @@ package body System.Generic_Array_Operations is
Target : Integer;
Source : Integer;
Factor : Scalar);
- -- Needs comments ???
+ -- Elementary row operation that subtracts Factor * M (Source, <>) from
+ -- M (Target, <>)
procedure Sub_Row
(M : in out Matrix;
@@ -158,27 +161,31 @@ package body System.Generic_Array_Operations is
pragma Assert (M'First (1) = N'First (1) and then
M'Last (1) = N'Last (1));
- function "abs" (X : Scalar) return Scalar is
- (if X < Zero then Zero - X else X);
+ -- The following are variations of the elementary matrix row operations:
+ -- row switching, row multiplication and row addition. Because in this
+ -- algorithm the addition factor is always a negated value, we chose to
+ -- use row subtraction instead. Similarly, instead of multiplying by
+ -- a reciprocal, we divide.
procedure Sub_Row
(M : in out Matrix;
Target : Integer;
Source : Integer;
Factor : Scalar);
- -- Needs commenting ???
+ -- Subtrace Factor * M (Source, <>) from M (Target, <>)
procedure Divide_Row
(M, N : in out Matrix;
Row : Integer;
Scale : Scalar);
- -- Needs commenting ???
+ -- Divide M (Row) and N (Row) by Scale, and update Det
procedure Switch_Row
(M, N : in out Matrix;
Row_1 : Integer;
Row_2 : Integer);
- -- Needs commenting ???
+ -- Exchange M (Row_1) and N (Row_1) with M (Row_2) and N (Row_2),
+ -- negating Det in the process.
-------------
-- Sub_Row --
@@ -254,8 +261,7 @@ package body System.Generic_Array_Operations is
end if;
end Switch_Row;
- I : Integer := M'First (1);
- -- Avoid use of I ???
+ Row : Integer := M'First (1);
-- Start of processing for Forward_Eliminate
@@ -264,35 +270,35 @@ package body System.Generic_Array_Operations is
for J in M'Range (2) loop
declare
- Max_I : Integer := I;
- Max_Abs : Scalar := Zero;
+ Max_Row : Integer := Row;
+ Max_Abs : Real'Base := 0.0;
begin
- -- Find best pivot in column J, starting in row I
+ -- Find best pivot in column J, starting in row Row
- for K in I .. M'Last (1) loop
+ for K in Row .. M'Last (1) loop
declare
- New_Abs : constant Scalar := abs M (K, J);
+ New_Abs : constant Real'Base := abs M (K, J);
begin
if Max_Abs < New_Abs then
Max_Abs := New_Abs;
- Max_I := K;
+ Max_Row := K;
end if;
end;
end loop;
- if Zero < Max_Abs then
- Switch_Row (M, N, I, Max_I);
- Divide_Row (M, N, I, M (I, J));
+ if Max_Abs > 0.0 then
+ Switch_Row (M, N, Row, Max_Row);
+ Divide_Row (M, N, Row, M (Row, J));
- for U in I + 1 .. M'Last (1) loop
- Sub_Row (N, U, I, M (U, J));
- Sub_Row (M, U, I, M (U, J));
+ for U in Row + 1 .. M'Last (1) loop
+ Sub_Row (N, U, Row, M (U, J));
+ Sub_Row (M, U, Row, M (U, J));
end loop;
- exit when I >= M'Last (1);
+ exit when Row >= M'Last (1);
- I := I + 1;
+ Row := Row + 1;
else
Det := Zero; -- Zero, but we don't have literals
@@ -329,9 +335,14 @@ package body System.Generic_Array_Operations is
-- L2_Norm --
-------------
- function L2_Norm (X : Vector) return Scalar is
+ function L2_Norm (X : X_Vector) return Result_Real'Base is
+ Sum : Result_Real'Base := 0.0;
begin
- return Sqrt (Inner_Product (X, X));
+ for J in X'Range loop
+ Sum := Sum + Result_Real'Base (abs X (J))**2;
+ end loop;
+
+ return Sqrt (Sum);
end L2_Norm;
----------------------------------
@@ -555,6 +566,56 @@ package body System.Generic_Array_Operations is
return R;
end Scalar_Vector_Elementwise_Operation;
+ ----------
+ -- Sqrt --
+ ----------
+
+ function Sqrt (X : Real'Base) return Real'Base is
+ Root, Next : Real'Base;
+
+ begin
+ -- Be defensive: any comparisons with NaN values will yield False.
+
+ if not (X > 0.0) then
+ if X = 0.0 then
+ return X;
+ else
+ raise Argument_Error;
+ end if;
+
+ elsif X > Real'Base'Last then
+ -- X is infinity, which is its own square root
+
+ return X;
+ end if;
+
+ -- Compute an initial estimate based on:
+
+ -- X = M * R**E and Sqrt (X) = Sqrt (M) * R**(E / 2.0),
+
+ -- where M is the mantissa, R is the radix and E the exponent.
+
+ -- By ignoring the mantissa and ignoring the case of an odd
+ -- exponent, we get a final error that is at most R. In other words,
+ -- the result has about a single bit precision.
+
+ Root := Real'Base (Real'Machine_Radix) ** (Real'Exponent (X) / 2);
+
+ -- Because of the poor initial estimate, use the Babylonian method of
+ -- computing the square root, as it is stable for all inputs. Every step
+ -- will roughly double the precision of the result. Just a few steps
+ -- suffice in most cases. Eight iterations should give about 2**8 bits
+ -- of precision.
+
+ for J in 1 .. 8 loop
+ Next := (Root + X / Root) / 2.0;
+ exit when Root = Next;
+ Root := Next;
+ end loop;
+
+ return Root;
+ end Sqrt;
+
---------------------------
-- Matrix_Matrix_Product --
---------------------------
@@ -590,6 +651,75 @@ package body System.Generic_Array_Operations is
return R;
end Matrix_Matrix_Product;
+ ----------------------------
+ -- Matrix_Vector_Solution --
+ ----------------------------
+
+ function Matrix_Vector_Solution (A : Matrix; X : Vector) return Vector is
+ N : constant Natural := A'Length (1);
+ MA : Matrix := A;
+ MX : Matrix (A'Range (1), 1 .. 1);
+ R : Vector (A'Range (2));
+ Det : Scalar;
+
+ begin
+ if A'Length (2) /= N then
+ raise Constraint_Error with "matrix is not square";
+ end if;
+
+ if X'Length /= N then
+ raise Constraint_Error with "incompatible vector length";
+ end if;
+
+ for J in 0 .. MX'Length (1) - 1 loop
+ MX (MX'First (1) + J, 1) := X (X'First + J);
+ end loop;
+
+ Forward_Eliminate (MA, MX, Det);
+ Back_Substitute (MA, MX);
+
+ for J in 0 .. R'Length - 1 loop
+ R (R'First + J) := MX (MX'First (1) + J, 1);
+ end loop;
+
+ return R;
+ end Matrix_Vector_Solution;
+
+ ----------------------------
+ -- Matrix_Matrix_Solution --
+ ----------------------------
+
+ function Matrix_Matrix_Solution (A, X : Matrix) return Matrix is
+ N : constant Natural := A'Length (1);
+ MA : Matrix (A'Range (2), A'Range (2));
+ MB : Matrix (A'Range (2), X'Range (2));
+ Det : Scalar;
+
+ begin
+ if A'Length (2) /= N then
+ raise Constraint_Error with "matrix is not square";
+ end if;
+
+ if X'Length (1) /= N then
+ raise Constraint_Error with "matrices have unequal number of rows";
+ end if;
+
+ for J in 0 .. A'Length (1) - 1 loop
+ for K in MA'Range (2) loop
+ MA (MA'First (1) + J, K) := A (A'First (1) + J, K);
+ end loop;
+
+ for K in MB'Range (2) loop
+ MB (MB'First (1) + J, K) := X (X'First (1) + J, K);
+ end loop;
+ end loop;
+
+ Forward_Eliminate (MA, MB, Det);
+ Back_Substitute (MA, MB);
+
+ return MB;
+ end Matrix_Matrix_Solution;
+
---------------------------
-- Matrix_Vector_Product --
---------------------------
diff --git a/gcc/ada/s-gearop.ads b/gcc/ada/s-gearop.ads
index 51e3b92c201..f401da219e3 100644
--- a/gcc/ada/s-gearop.ads
+++ b/gcc/ada/s-gearop.ads
@@ -65,12 +65,14 @@ pragma Pure (Generic_Array_Operations);
generic
type Scalar is private;
+ type Real is digits <>;
type Matrix is array (Integer range <>, Integer range <>) of Scalar;
+ with function "abs" (Right : Scalar) return Real'Base is <>;
with function "-" (Left, Right : Scalar) return Scalar is <>;
with function "*" (Left, Right : Scalar) return Scalar is <>;
with function "/" (Left, Right : Scalar) return Scalar is <>;
- with function "<" (Left, Right : Scalar) return Boolean is <>;
- Zero, One : Scalar;
+ Zero : Scalar;
+ One : Scalar;
procedure Forward_Eliminate
(M : in out Matrix;
N : in out Matrix;
@@ -291,11 +293,12 @@ pragma Pure (Generic_Array_Operations);
-------------
generic
- type Scalar is private;
- type Vector is array (Integer range <>) of Scalar;
- with function Inner_Product (Left, Right : Vector) return Scalar is <>;
- with function Sqrt (X : Scalar) return Scalar is <>;
- function L2_Norm (X : Vector) return Scalar;
+ type X_Scalar is private;
+ type Result_Real is digits <>;
+ type X_Vector is array (Integer range <>) of X_Scalar;
+ with function "abs" (Right : X_Scalar) return Result_Real is <>;
+ with function Sqrt (X : Result_Real'Base) return Result_Real'Base is <>;
+ function L2_Norm (X : X_Vector) return Result_Real'Base;
-------------------
-- Outer_Product --
@@ -387,6 +390,43 @@ pragma Pure (Generic_Array_Operations);
(Left : Left_Matrix;
Right : Right_Matrix) return Result_Matrix;
+ ----------------------------
+ -- Matrix_Vector_Solution --
+ ----------------------------
+
+ generic
+ type Scalar is private;
+ type Vector is array (Integer range <>) of Scalar;
+ type Matrix is array (Integer range <>, Integer range <>) of Scalar;
+ with procedure Back_Substitute (M, N : in out Matrix) is <>;
+ with procedure Forward_Eliminate
+ (M : in out Matrix;
+ N : in out Matrix;
+ Det : out Scalar) is <>;
+ function Matrix_Vector_Solution (A : Matrix; X : Vector) return Vector;
+
+ ----------------------------
+ -- Matrix_Matrix_Solution --
+ ----------------------------
+
+ generic
+ type Scalar is private;
+ type Matrix is array (Integer range <>, Integer range <>) of Scalar;
+ with procedure Back_Substitute (M, N : in out Matrix) is <>;
+ with procedure Forward_Eliminate
+ (M : in out Matrix;
+ N : in out Matrix;
+ Det : out Scalar) is <>;
+ function Matrix_Matrix_Solution (A : Matrix; X : Matrix) return Matrix;
+
+ ----------
+ -- Sqrt --
+ ----------
+
+ generic
+ type Real is digits <>;
+ function Sqrt (X : Real'Base) return Real'Base;
+
-----------------
-- Swap_Column --
-----------------
diff --git a/gcc/ada/s-linux-alpha.ads b/gcc/ada/s-linux-alpha.ads
index ba72719f8db..a700c9720e6 100644
--- a/gcc/ada/s-linux-alpha.ads
+++ b/gcc/ada/s-linux-alpha.ads
@@ -35,8 +35,6 @@
-- PLEASE DO NOT add any with-clauses to this package or remove the pragma
-- Preelaborate. This package is designed to be a bottom-level (leaf) package.
-with Interfaces.C;
-
package System.Linux is
pragma Preelaborate;
diff --git a/gcc/ada/s-linux-sparc.ads b/gcc/ada/s-linux-sparc.ads
index 756d69d8f30..3ba20da4d5c 100644
--- a/gcc/ada/s-linux-sparc.ads
+++ b/gcc/ada/s-linux-sparc.ads
@@ -35,8 +35,6 @@
-- PLEASE DO NOT add any with-clauses to this package or remove the pragma
-- Preelaborate. This package is designed to be a bottom-level (leaf) package
-with Interfaces.C;
-
package System.Linux is
pragma Preelaborate;
diff --git a/gcc/ada/s-osinte-freebsd.ads b/gcc/ada/s-osinte-freebsd.ads
index d3d5c8763e4..cbd2a2df428 100644
--- a/gcc/ada/s-osinte-freebsd.ads
+++ b/gcc/ada/s-osinte-freebsd.ads
@@ -645,7 +645,10 @@ private
type clockid_t is new int;
CLOCK_REALTIME : constant clockid_t := 0;
- CLOCK_MONOTONIC : constant clockid_t := 4;
+ CLOCK_MONOTONIC : constant clockid_t := 0;
+ -- On FreeBSD, pthread_cond_timedwait assumes a CLOCK_REALTIME time by
+ -- default (unless pthread_condattr_setclock is used to set an alternate
+ -- clock).
type pthread_t is new System.Address;
type pthread_attr_t is new System.Address;
diff --git a/gcc/ada/s-regpat.adb b/gcc/ada/s-regpat.adb
index 53218978a0b..cee229ef6b5 100755
--- a/gcc/ada/s-regpat.adb
+++ b/gcc/ada/s-regpat.adb
@@ -7,7 +7,7 @@
-- B o d y --
-- --
-- Copyright (C) 1986 by University of Toronto. --
--- Copyright (C) 1999-2010, AdaCore --
+-- Copyright (C) 1999-2011, AdaCore --
-- --
-- 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- --
@@ -2013,11 +2013,13 @@ package body System.Regpat is
Must_Have_Length => Dummy.Must_Have_Length,
Paren_Count => Dummy.Paren_Count,
Flags => Dummy.Flags,
- Program => Dummy.Program
- (Dummy.Program'First .. Dummy.Program'First + Size - 1));
+ Program =>
+ Dummy.Program
+ (Dummy.Program'First .. Dummy.Program'First + Size - 1));
else
-- We have to recompile now that we know the size
- -- ??? Can we use Ada05's return construct ?
+ -- ??? Can we use Ada 2005's return construct ?
+
declare
Result : Pattern_Matcher (Size);
begin
diff --git a/gcc/ada/s-rident.ads b/gcc/ada/s-rident.ads
index dd9ef16b22c..1c306e34664 100644
--- a/gcc/ada/s-rident.ads
+++ b/gcc/ada/s-rident.ads
@@ -41,6 +41,8 @@
-- so we can do the instantiation under control of Discard_Names to remove
-- the tables.
+pragma Compiler_Unit;
+
generic
package System.Rident is
pragma Preelaborate;
diff --git a/gcc/ada/s-stopoo.ads b/gcc/ada/s-stopoo.ads
index 1c4d12754a0..e2d66ff747d 100644
--- a/gcc/ada/s-stopoo.ads
+++ b/gcc/ada/s-stopoo.ads
@@ -65,6 +65,14 @@ private
type Root_Storage_Pool is abstract
new Ada.Finalization.Limited_Controlled with null record;
+ type Root_Storage_Pool_Ptr is access all Root_Storage_Pool'Class;
+ for Root_Storage_Pool_Ptr'Storage_Size use 0;
+ -- Type of the BIP_Storage_Pool extra parameter (see Exp_Ch6). The
+ -- Storage_Size clause is necessary, because otherwise we have a
+ -- chicken&egg problem; we can't be creating collection finalization code
+ -- in this low-level package, because that involves Pool_Global, which
+ -- imports this package.
+
-- ??? Are these two still needed? It might be possible to use Subpools.
-- Allocate_Any_Controlled / Deallocate_Any_Controlled for non-controlled
-- objects.
diff --git a/gcc/ada/s-taprop-posix.adb b/gcc/ada/s-taprop-posix.adb
index 1dec99966ee..425508a32c2 100644
--- a/gcc/ada/s-taprop-posix.adb
+++ b/gcc/ada/s-taprop-posix.adb
@@ -1089,9 +1089,10 @@ package body System.Task_Primitives.Operations is
Result := pthread_mutex_destroy (S.L'Access);
pragma Assert (Result = 0);
- if Result = ENOMEM then
- raise Storage_Error;
- end if;
+ -- Storage_Error is propagated as intended if the allocation of the
+ -- underlying OS entities fails.
+
+ raise Storage_Error;
end if;
Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
@@ -1101,11 +1102,13 @@ package body System.Task_Primitives.Operations is
Result := pthread_mutex_destroy (S.L'Access);
pragma Assert (Result = 0);
- if Result = ENOMEM then
- Result := pthread_condattr_destroy (Cond_Attr'Access);
- pragma Assert (Result = 0);
- raise Storage_Error;
- end if;
+ Result := pthread_condattr_destroy (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+
+ -- Storage_Error is propagated as intended if the allocation of the
+ -- underlying OS entities fails.
+
+ raise Storage_Error;
end if;
Result := pthread_condattr_destroy (Cond_Attr'Access);
diff --git a/gcc/ada/s-tasren.adb b/gcc/ada/s-tasren.adb
index 4034e61af17..e2541a106fd 100644
--- a/gcc/ada/s-tasren.adb
+++ b/gcc/ada/s-tasren.adb
@@ -1502,7 +1502,7 @@ package body System.Tasking.Rendezvous is
-- Null_Body. Defer abort until it gets into the accept body.
Uninterpreted_Data := Self_Id.Common.Call.Uninterpreted_Data;
- Initialization.Defer_Abort (Self_Id);
+ Initialization.Defer_Abort_Nestable (Self_Id);
STPO.Unlock (Self_Id);
when Accept_Alternative_Completed =>
diff --git a/gcc/ada/s-tpopde-vms.ads b/gcc/ada/s-tpopde-vms.ads
index aadafa6490b..e690f306e7a 100644
--- a/gcc/ada/s-tpopde-vms.ads
+++ b/gcc/ada/s-tpopde-vms.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2000-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 2000-2011, Free Software Foundation, Inc. --
-- --
-- GNARL 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- --
@@ -36,7 +36,7 @@ package System.Task_Primitives.Operations.DEC is
procedure Interrupt_AST_Handler (ID : Address);
pragma Convention (C, Interrupt_AST_Handler);
- -- Handles the AST for Ada95 Interrupts
+ -- Handles the AST for Ada 95 Interrupts
procedure RMS_AST_Handler (ID : Address);
-- Handles the AST for RMS_Asynch_Operations
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 657ece339b1..011a444cf0d 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -1675,8 +1675,12 @@ package body Sem_Aggr is
-- unless the expression covers a single component, or the
-- expander is inactive.
+ -- In Alfa mode, expressions that can perform side-effects will be
+ -- recognized by the gnat2why back-end, and the whole subprogram
+ -- will be ignored. So semantic analysis can be performed safely.
+
if Single_Elmt
- or else not Expander_Active
+ or else not Full_Expander_Active
or else In_Spec_Expression
then
Analyze_And_Resolve (Expr, Component_Typ);
@@ -3121,6 +3125,13 @@ package body Sem_Aggr is
Expr := New_Copy_Tree (Expression (Parent (Compon)));
+ -- Component may have no default, in which case the
+ -- expression is empty and the component is default-
+ -- initialized, but an association for the component
+ -- exists, and it is not covered by an others clause.
+
+ return Expr;
+
else
if Present (Next (Selector_Name)) then
Expr := New_Copy_Tree (Expression (Assoc));
@@ -3414,7 +3425,7 @@ package body Sem_Aggr is
Selector_Name);
return;
- -- (Ada2005): If this is an association with a box,
+ -- (Ada 2005): If this is an association with a box,
-- indicate that the association need not represent
-- any component.
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index 738edda77fd..ae7edbf9dc2 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -264,6 +264,10 @@ package body Sem_Attr is
-- If the prefix type is an enumeration type, set all its literals
-- as referenced, since the image function could possibly end up
-- referencing any of the literals indirectly. Same for Enum_Val.
+ -- Set the flag only if the reference is in the main code unit. Same
+ -- restriction when resolving 'Value; otherwise an improperly set
+ -- reference when analyzing an inlined body will lose a proper warning
+ -- on a useless with_clause.
procedure Check_Fixed_Point_Type;
-- Verify that prefix of attribute N is a fixed type
@@ -1225,8 +1229,17 @@ package body Sem_Attr is
procedure Check_Enum_Image is
Lit : Entity_Id;
+
begin
- if Is_Enumeration_Type (P_Base_Type) then
+ -- When an enumeration type appears in an attribute reference, all
+ -- literals of the type are marked as referenced. This must only be
+ -- done if the attribute reference appears in the current source.
+ -- Otherwise the information on references may differ between a
+ -- normal compilation and one that performs inlining.
+
+ if Is_Enumeration_Type (P_Base_Type)
+ and then In_Extended_Main_Code_Unit (N)
+ then
Lit := First_Literal (P_Base_Type);
while Present (Lit) loop
Set_Referenced (Lit);
@@ -2125,7 +2138,7 @@ package body Sem_Attr is
case Attr_Id is
- -- Attributes related to Ada2012 iterators. Attribute specifications
+ -- Attributes related to Ada 2012 iterators. Attribute specifications
-- exist for these, but they cannot be queried.
when Attribute_Constant_Indexing |
@@ -5031,7 +5044,15 @@ package body Sem_Attr is
-- Case of enumeration type
- if Is_Enumeration_Type (P_Type) then
+ -- When an enumeration type appears in an attribute reference, all
+ -- literals of the type are marked as referenced. This must only be
+ -- done if the attribute reference appears in the current source.
+ -- Otherwise the information on references may differ between a
+ -- normal compilation and one that performs inlining.
+
+ if Is_Enumeration_Type (P_Type)
+ and then In_Extended_Main_Code_Unit (N)
+ then
Check_Restriction (No_Enumeration_Maps, N);
-- Mark all enumeration literals as referenced, since the use of
@@ -6120,7 +6141,7 @@ package body Sem_Attr is
case Id is
- -- Attributes related to Ada2012 iterators (placeholder ???)
+ -- Attributes related to Ada 2012 iterators (placeholder ???)
when Attribute_Constant_Indexing => null;
when Attribute_Default_Iterator => null;
diff --git a/gcc/ada/sem_attr.ads b/gcc/ada/sem_attr.ads
index 0e8561ae729..a12d5a70a9e 100644
--- a/gcc/ada/sem_attr.ads
+++ b/gcc/ada/sem_attr.ads
@@ -607,12 +607,12 @@ package Sem_Attr is
(Typ : Entity_Id;
Nam : TSS_Name_Type;
Partial_View : Entity_Id := Empty) return Boolean;
- -- For a limited type Typ, return True iff the given attribute is
- -- available. For Ada 05, availability is defined by 13.13.2(36/1). For Ada
- -- 95, an attribute is considered to be available if it has been specified
- -- using an attribute definition clause for the type, or for its full view,
- -- or for an ancestor of either. Parameter Partial_View is used only
- -- internally, when checking for an attribute definition clause that is not
- -- visible (Ada 95 only).
+ -- For a limited type Typ, return True if and only if the given attribute
+ -- is available. For Ada 2005, availability is defined by 13.13.2(36/1).
+ -- For Ada 95, an attribute is considered to be available if it has been
+ -- specified using an attribute definition clause for the type, or for its
+ -- full view, or for an ancestor of either. Parameter Partial_View is used
+ -- only internally, when checking for an attribute definition clause that
+ -- is not visible (Ada 95 only).
end Sem_Attr;
diff --git a/gcc/ada/sem_cat.adb b/gcc/ada/sem_cat.adb
index 58aaee1d573..04cf958ca92 100644
--- a/gcc/ada/sem_cat.adb
+++ b/gcc/ada/sem_cat.adb
@@ -900,7 +900,7 @@ package body Sem_Cat is
-- If the type is private, it must have the Ada 2005 pragma
-- Has_Preelaborable_Initialization.
-- The check is omitted within predefined units. This is probably
- -- obsolete code to fix the Ada95 weakness in this area ???
+ -- obsolete code to fix the Ada 95 weakness in this area ???
if Is_Private_Type (T)
and then not Has_Pragma_Preelab_Init (T)
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index c6f18da4e54..98a57e2556e 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -208,7 +208,7 @@ package body Sem_Ch10 is
-- Limited_With_Clauses --
--------------------------
- -- Limited_With clauses are the mechanism chosen for Ada05 to support
+ -- Limited_With clauses are the mechanism chosen for Ada 2005 to support
-- mutually recursive types declared in different units. A limited_with
-- clause that names package P in the context of unit U makes the types
-- declared in the visible part of P available within U, but with the
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index dbf3896bdb3..b1963f3fdd4 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -258,7 +258,7 @@ package body Sem_Ch12 is
-- are not accessible outside of the instance.
-- In a generic, a formal package is treated like a special instantiation.
- -- Our Ada95 compiler handled formals with and without box in different
+ -- Our Ada 95 compiler handled formals with and without box in different
-- ways. With partial parametrization, we use a single model for both.
-- We create a package declaration that consists of the specification of
-- the generic package, and a set of declarations that map the actuals
@@ -1565,16 +1565,22 @@ package body Sem_Ch12 is
-- static. For all scalar types we introduce an anonymous base type, with
-- the same attributes. We choose the corresponding integer type to be
-- Standard_Integer.
+ -- Here and in other similar routines, the Sloc of the generated internal
+ -- type must be the same as the sloc of the defining identifier of the
+ -- formal type declaration, to provide proper source navigation.
procedure Analyze_Formal_Decimal_Fixed_Point_Type
(T : Entity_Id;
Def : Node_Id)
is
- Loc : constant Source_Ptr := Sloc (Def);
- Base : constant Entity_Id :=
- New_Internal_Entity
- (E_Decimal_Fixed_Point_Type,
- Current_Scope, Sloc (Def), 'G');
+ Loc : constant Source_Ptr := Sloc (Def);
+
+ Base : constant Entity_Id :=
+ New_Internal_Entity
+ (E_Decimal_Fixed_Point_Type,
+ Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
Int_Base : constant Entity_Id := Standard_Integer;
Delta_Val : constant Ureal := Ureal_1;
Digs_Val : constant Uint := Uint_6;
@@ -1714,7 +1720,9 @@ package body Sem_Ch12 is
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Floating_Point_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Floating_Point_Type, Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
begin
Enter_Name (T);
Set_Ekind (T, E_Enumeration_Subtype);
@@ -1762,7 +1770,8 @@ package body Sem_Ch12 is
procedure Analyze_Formal_Floating_Type (T : Entity_Id; Def : Node_Id) is
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Floating_Point_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Floating_Point_Type, Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
begin
-- The various semantic attributes are taken from the predefined type
@@ -1980,7 +1989,9 @@ package body Sem_Ch12 is
Loc : constant Source_Ptr := Sloc (Def);
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Ordinary_Fixed_Point_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Ordinary_Fixed_Point_Type, Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
begin
-- The semantic attributes are set for completeness only, their values
-- will never be used, since all properties of the type are non-static.
@@ -2403,7 +2414,9 @@ package body Sem_Ch12 is
is
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Signed_Integer_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Signed_Integer_Type,
+ Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
begin
Enter_Name (T);
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 0895eb68652..5790b9a85a0 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -3365,10 +3365,22 @@ package body Sem_Ch13 is
-- No statements other than code statements, pragmas, and labels.
-- Again we allow certain internally generated statements.
+ -- In Ada 2012, qualified expressions are names, and the code
+ -- statement is initially parsed as a procedure call.
+
Stmt := First (Statements (HSS));
while Present (Stmt) loop
StmtO := Original_Node (Stmt);
- if Comes_From_Source (StmtO)
+
+ -- A procedure call transformed into a code statement is OK.
+
+ if Ada_Version >= Ada_2012
+ and then Nkind (StmtO) = N_Procedure_Call_Statement
+ and then Nkind (Name (StmtO)) = N_Qualified_Expression
+ then
+ null;
+
+ elsif Comes_From_Source (StmtO)
and then not Nkind_In (StmtO, N_Pragma,
N_Label,
N_Code_Statement)
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index dd48cff4d17..cd833d5d04e 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -706,11 +706,9 @@ package body Sem_Ch3 is
(Related_Nod : Node_Id;
N : Node_Id) return Entity_Id
is
- Loc : constant Source_Ptr := Sloc (Related_Nod);
Anon_Type : Entity_Id;
Anon_Scope : Entity_Id;
Desig_Type : Entity_Id;
- Decl : Entity_Id;
Enclosing_Prot_Type : Entity_Id := Empty;
begin
@@ -889,7 +887,7 @@ package body Sem_Ch3 is
-- proper Master for the created tasks.
if Nkind (Related_Nod) = N_Object_Declaration
- and then Expander_Active
+ and then Expander_Active
then
if Is_Interface (Desig_Type)
and then Is_Limited_Record (Desig_Type)
@@ -901,28 +899,9 @@ package body Sem_Ch3 is
elsif Has_Task (Desig_Type)
and then Comes_From_Source (Related_Nod)
- and then not Restriction_Active (No_Task_Hierarchy)
then
- if not Has_Master_Entity (Current_Scope) then
- Decl :=
- Make_Object_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_uMaster),
- Constant_Present => True,
- Object_Definition =>
- New_Reference_To (RTE (RE_Master_Id), Loc),
- Expression =>
- Make_Explicit_Dereference (Loc,
- New_Reference_To (RTE (RE_Current_Master), Loc)));
-
- Insert_Before (Related_Nod, Decl);
- Analyze (Decl);
-
- Set_Master_Id (Anon_Type, Defining_Identifier (Decl));
- Set_Has_Master_Entity (Current_Scope);
- else
- Build_Master_Renaming (Related_Nod, Anon_Type);
- end if;
+ Build_Master_Entity (Defining_Identifier (Related_Nod));
+ Build_Master_Renaming (Anon_Type);
end if;
end if;
@@ -9026,7 +9005,7 @@ package body Sem_Ch3 is
-- The partial view of T may have been a private extension, for
-- which inherited functions dispatching on result are abstract.
-- If the full view is a null extension, there is no need for
- -- overriding in Ada2005, but wrappers need to be built for them
+ -- overriding in Ada 2005, but wrappers need to be built for them
-- (see exp_ch3, Build_Controlling_Function_Wrappers).
if Is_Null_Extension (T)
@@ -16909,6 +16888,36 @@ package body Sem_Ch3 is
when N_Attribute_Reference =>
return Attribute_Name (Original_Node (Exp)) = Name_Input;
+ -- For a conditional expression, all dependent expressions must be
+ -- legal constructs.
+
+ when N_Conditional_Expression =>
+ declare
+ Then_Expr : constant Node_Id :=
+ Next (First (Expressions (Original_Node (Exp))));
+ Else_Expr : constant Node_Id := Next (Then_Expr);
+ begin
+ return OK_For_Limited_Init_In_05 (Typ, Then_Expr)
+ and then OK_For_Limited_Init_In_05 (Typ, Else_Expr);
+ end;
+
+ when N_Case_Expression =>
+ declare
+ Alt : Node_Id;
+
+ begin
+ Alt := First (Alternatives (Original_Node (Exp)));
+ while Present (Alt) loop
+ if not OK_For_Limited_Init_In_05 (Typ, Expression (Alt)) then
+ return False;
+ end if;
+
+ Next (Alt);
+ end loop;
+
+ return True;
+ end;
+
when others =>
return False;
end case;
@@ -18287,7 +18296,7 @@ package body Sem_Ch3 is
-- Look up tree to find an appropriate insertion point. We
-- can't just use insert_actions because later processing
- -- depends on the insertion node. Prior to Ada2012 the
+ -- depends on the insertion node. Prior to Ada 2012 the
-- insertion point could only be a declaration or a loop, but
-- quantified expressions can appear within any context in an
-- expression, and the insertion point can be any statement,
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index 742e1c9afae..efc76f11398 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -3114,63 +3114,61 @@ package body Sem_Ch4 is
if Present (Next_Actual (Act2)) then
return;
+ end if;
- elsif Op_Name = Name_Op_Add
- or else Op_Name = Name_Op_Subtract
- or else Op_Name = Name_Op_Multiply
- or else Op_Name = Name_Op_Divide
- or else Op_Name = Name_Op_Mod
- or else Op_Name = Name_Op_Rem
- or else Op_Name = Name_Op_Expon
- then
- Find_Arithmetic_Types (Act1, Act2, Op_Id, N);
+ -- Otherwise action depends on operator
- elsif Op_Name = Name_Op_And
- or else Op_Name = Name_Op_Or
- or else Op_Name = Name_Op_Xor
- then
- Find_Boolean_Types (Act1, Act2, Op_Id, N);
+ case Op_Name is
+ when Name_Op_Add |
+ Name_Op_Subtract |
+ Name_Op_Multiply |
+ Name_Op_Divide |
+ Name_Op_Mod |
+ Name_Op_Rem |
+ Name_Op_Expon =>
+ Find_Arithmetic_Types (Act1, Act2, Op_Id, N);
- elsif Op_Name = Name_Op_Lt
- or else Op_Name = Name_Op_Le
- or else Op_Name = Name_Op_Gt
- or else Op_Name = Name_Op_Ge
- then
- Find_Comparison_Types (Act1, Act2, Op_Id, N);
+ when Name_Op_And |
+ Name_Op_Or |
+ Name_Op_Xor =>
+ Find_Boolean_Types (Act1, Act2, Op_Id, N);
- elsif Op_Name = Name_Op_Eq
- or else Op_Name = Name_Op_Ne
- then
- Find_Equality_Types (Act1, Act2, Op_Id, N);
+ when Name_Op_Lt |
+ Name_Op_Le |
+ Name_Op_Gt |
+ Name_Op_Ge =>
+ Find_Comparison_Types (Act1, Act2, Op_Id, N);
- elsif Op_Name = Name_Op_Concat then
- Find_Concatenation_Types (Act1, Act2, Op_Id, N);
+ when Name_Op_Eq |
+ Name_Op_Ne =>
+ Find_Equality_Types (Act1, Act2, Op_Id, N);
- -- Is this else null correct, or should it be an abort???
+ when Name_Op_Concat =>
+ Find_Concatenation_Types (Act1, Act2, Op_Id, N);
- else
- null;
- end if;
+ -- Is this when others, or should it be an abort???
+
+ when others =>
+ null;
+ end case;
-- Unary operator case
else
- if Op_Name = Name_Op_Subtract or else
- Op_Name = Name_Op_Add or else
- Op_Name = Name_Op_Abs
- then
- Find_Unary_Types (Act1, Op_Id, N);
+ case Op_Name is
+ when Name_Op_Subtract |
+ Name_Op_Add |
+ Name_Op_Abs =>
+ Find_Unary_Types (Act1, Op_Id, N);
- elsif
- Op_Name = Name_Op_Not
- then
- Find_Negation_Types (Act1, Op_Id, N);
+ when Name_Op_Not =>
+ Find_Negation_Types (Act1, Op_Id, N);
- -- Is this else null correct, or should it be an abort???
+ -- Is this when others correct, or should it be an abort???
- else
- null;
- end if;
+ when others =>
+ null;
+ end case;
end if;
end Analyze_Operator_Call;
@@ -3434,8 +3432,8 @@ package body Sem_Ch4 is
-- of the high bound.
procedure Check_Universal_Expression (N : Node_Id);
- -- In Ada83, reject bounds of a universal range that are not
- -- literals or entity names.
+ -- In Ada83, reject bounds of a universal range that are not literals or
+ -- entity names.
-----------------------
-- Check_Common_Type --
@@ -5548,9 +5546,15 @@ package body Sem_Ch4 is
end if;
if T1 /= Standard_Void_Type
- and then not Is_Limited_Type (T1)
- and then not Is_Limited_Composite (T1)
and then Has_Compatible_Type (R, T1)
+ and then
+ ((not Is_Limited_Type (T1)
+ and then not Is_Limited_Composite (T1))
+
+ or else
+ (Is_Array_Type (T1)
+ and then not Is_Limited_Type (Component_Type (T1))
+ and then Available_Full_View_Of_Component (T1)))
then
if Found
and then Base_Type (T1) /= Base_Type (T_F)
@@ -6428,7 +6432,7 @@ package body Sem_Ch4 is
begin
- -- Check whether type has a specified indexing aspect.
+ -- Check whether type has a specified indexing aspect
Func_Name := Empty;
Is_Var := False;
@@ -6437,7 +6441,7 @@ package body Sem_Ch4 is
while Present (Ritem) loop
if Nkind (Ritem) = N_Aspect_Specification then
- -- Prefer Variable_Indexing, but will settle for Constant.
+ -- Prefer Variable_Indexing, but will settle for Constant
if Get_Aspect_Id (Chars (Identifier (Ritem))) =
Aspect_Constant_Indexing
@@ -6523,7 +6527,7 @@ package body Sem_Ch4 is
if Success then
Set_Etype (Name (N), It.Typ);
- -- Add implicit dereference interpretation.
+ -- Add implicit dereference interpretation
Disc := First_Discriminant (Etype (It.Nam));
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 875eb1c0778..1b0f919d3ff 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -2068,7 +2068,7 @@ package body Sem_Ch5 is
Set_Parent (D_Copy, Parent (DS));
Pre_Analyze_Range (D_Copy);
- -- Ada2012: If the domain of iteration is a function call,
+ -- Ada 2012: If the domain of iteration is a function call,
-- it is the new iterator form.
-- We have also implemented the shorter form : for X in S
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index a9a45bc6445..3dbf782b60b 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -78,6 +78,7 @@ with Snames; use Snames;
with Stringt; use Stringt;
with Style;
with Stylesw; use Stylesw;
+with Targparm; use Targparm;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
with Urealp; use Urealp;
@@ -387,9 +388,9 @@ package body Sem_Ch6 is
begin
Analyze (P);
- -- A call of the form A.B (X) may be an Ada05 call, which is rewritten
- -- as B (A, X). If the rewriting is successful, the call has been
- -- analyzed and we just return.
+ -- A call of the form A.B (X) may be an Ada 2005 call, which is
+ -- rewritten as B (A, X). If the rewriting is successful, the call
+ -- has been analyzed and we just return.
if Nkind (P) = N_Selected_Component
and then Name (N) /= P
@@ -452,7 +453,18 @@ package body Sem_Ch6 is
-- incompatibility with Ada 95. Not clear whether this should be
-- enforced yet or perhaps controllable with special switch. ???
- if Is_Limited_Type (R_Type)
+ -- A limited interface that is not immutably limited is OK.
+
+ if Is_Limited_Interface (R_Type)
+ and then
+ not (Is_Task_Interface (R_Type)
+ or else Is_Protected_Interface (R_Type)
+ or else Is_Synchronized_Interface (R_Type))
+ then
+ null;
+
+ elsif Is_Limited_Type (R_Type)
+ and then not Is_Interface (R_Type)
and then Comes_From_Source (N)
and then not In_Instance_Body
and then not OK_For_Limited_Init_In_05 (R_Type, Expr)
@@ -484,7 +496,7 @@ package body Sem_Ch6 is
elsif Warn_On_Ada_2005_Compatibility or GNAT_Mode then
if Inside_A_Generic then
Error_Msg_N
- ("return of limited object not permitted in Ada2005 "
+ ("return of limited object not permitted in Ada 2005 "
& "(RM-2005 6.5(5.5/2))?", Expr);
elsif Is_Immutably_Limited_Type (R_Type) then
@@ -1329,6 +1341,15 @@ package body Sem_Ch6 is
Analyze (P);
Analyze_Call_And_Resolve;
+ -- In Ada 2012. a qualified expression is a name, but it cannot be a
+ -- procedure name, so the construct can only be a qualified expression.
+
+ elsif Nkind (P) = N_Qualified_Expression
+ and then Ada_Version >= Ada_2012
+ then
+ Rewrite (N, Make_Code_Statement (Loc, Expression => P));
+ Analyze (N);
+
-- Anything else is an error
else
@@ -2370,7 +2391,7 @@ package body Sem_Ch6 is
-- expansion has generated an equivalent type that is used when
-- elaborating the body.
- -- An exception in the case of Ada2012, AI05-177: The bodies
+ -- An exception in the case of Ada 2012, AI05-177: The bodies
-- created for expression functions do not freeze.
if No (Spec_Id)
@@ -6123,7 +6144,7 @@ package body Sem_Ch6 is
Desig_2 : Entity_Id;
begin
- -- In Ada2005, access constant indicators must match for
+ -- In Ada 2005, access constant indicators must match for
-- subtype conformance.
if Ada_Version >= Ada_2005
@@ -6440,6 +6461,8 @@ package body Sem_Ch6 is
if Ada_Version >= Ada_2005 and then Is_Build_In_Place_Function (E) then
declare
Result_Subt : constant Entity_Id := Etype (E);
+ Full_Subt : constant Entity_Id := Available_View (Result_Subt);
+ Formal_Typ : Entity_Id;
Discard : Entity_Id;
pragma Warnings (Off, Discard);
@@ -6462,6 +6485,19 @@ package body Sem_Ch6 is
Add_Extra_Formal
(E, Standard_Natural,
E, BIP_Formal_Suffix (BIP_Alloc_Form));
+
+ -- Add BIP_Storage_Pool, in case BIP_Alloc_Form indicates to
+ -- use a user-defined pool. This formal is not added on
+ -- .NET/JVM/ZFP as those targets do not support pools.
+
+ if VM_Target = No_VM
+ and then RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Discard :=
+ Add_Extra_Formal
+ (E, RTE (RE_Root_Storage_Pool_Ptr),
+ E, BIP_Formal_Suffix (BIP_Storage_Pool));
+ end if;
end if;
-- In the case of functions whose result type needs finalization,
@@ -6478,11 +6514,11 @@ package body Sem_Ch6 is
-- master of the tasks to be created, and the caller's activation
-- chain.
- if Has_Task (Available_View (Result_Subt)) then
+ if Has_Task (Full_Subt) then
Discard :=
Add_Extra_Formal
(E, RTE (RE_Master_Id),
- E, BIP_Formal_Suffix (BIP_Master));
+ E, BIP_Formal_Suffix (BIP_Task_Master));
Discard :=
Add_Extra_Formal
(E, RTE (RE_Activation_Chain_Access),
@@ -6492,31 +6528,27 @@ package body Sem_Ch6 is
-- All build-in-place functions get an extra formal that will be
-- passed the address of the return object within the caller.
- declare
- Formal_Type : constant Entity_Id :=
- Create_Itype
- (E_Anonymous_Access_Type, E,
- Scope_Id => Scope (E));
- begin
- Set_Directly_Designated_Type (Formal_Type, Result_Subt);
- Set_Etype (Formal_Type, Formal_Type);
- Set_Depends_On_Private
- (Formal_Type, Has_Private_Component (Formal_Type));
- Set_Is_Public (Formal_Type, Is_Public (Scope (Formal_Type)));
- Set_Is_Access_Constant (Formal_Type, False);
+ Formal_Typ :=
+ Create_Itype (E_Anonymous_Access_Type, E, Scope_Id => Scope (E));
- -- Ada 2005 (AI-50217): Propagate the attribute that indicates
- -- the designated type comes from the limited view (for
- -- back-end purposes).
+ Set_Directly_Designated_Type (Formal_Typ, Result_Subt);
+ Set_Etype (Formal_Typ, Formal_Typ);
+ Set_Depends_On_Private
+ (Formal_Typ, Has_Private_Component (Formal_Typ));
+ Set_Is_Public (Formal_Typ, Is_Public (Scope (Formal_Typ)));
+ Set_Is_Access_Constant (Formal_Typ, False);
- Set_From_With_Type (Formal_Type, From_With_Type (Result_Subt));
+ -- Ada 2005 (AI-50217): Propagate the attribute that indicates
+ -- the designated type comes from the limited view (for back-end
+ -- purposes).
- Layout_Type (Formal_Type);
+ Set_From_With_Type (Formal_Typ, From_With_Type (Result_Subt));
- Discard :=
- Add_Extra_Formal
- (E, Formal_Type, E, BIP_Formal_Suffix (BIP_Object_Access));
- end;
+ Layout_Type (Formal_Typ);
+
+ Discard :=
+ Add_Extra_Formal
+ (E, Formal_Typ, E, BIP_Formal_Suffix (BIP_Object_Access));
end;
end if;
end Create_Extra_Formals;
@@ -8714,7 +8746,7 @@ package body Sem_Ch6 is
-- inherited in a derivation, or when an inherited operation
-- of a tagged full type overrides the inherited operation of
-- a private extension. Ada 83 had a special rule for the
- -- literal case. In Ada95, the later implicit operation hides
+ -- literal case. In Ada 95, the later implicit operation hides
-- the former, and the literal is always the former. In the
-- odd case where both are derived operations declared at the
-- same point, both operations should be declared, and in that
@@ -10251,7 +10283,7 @@ package body Sem_Ch6 is
if Nkind (Parameter_Type (Spec)) = N_Access_Definition then
- -- Ada 2005 (AI-231): In Ada95, access parameters are always non-
+ -- Ada 2005 (AI-231): In Ada 95, access parameters are always non-
-- null; In Ada 2005, only if then null_exclusion is explicit.
if Ada_Version < Ada_2005
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 6c561dafc71..17f802fc14e 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -2398,7 +2398,14 @@ package body Sem_Ch8 is
elsif not Is_Entity_Name (Nam)
or else not Is_Overloadable (Entity (Nam))
then
- Error_Msg_N ("expect valid subprogram name in renaming", N);
+ -- Do not mention the renaming if it comes from an instance
+
+ if not Is_Actual then
+ Error_Msg_N ("expect valid subprogram name in renaming", N);
+ else
+ Error_Msg_NE ("no visible subprogram for formal&", N, Nam);
+ end if;
+
return;
end if;
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index b4a4c456dc5..4b284cd9599 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -1163,7 +1163,12 @@ package body Sem_Ch9 is
begin
if No_Run_Time_Mode then
Error_Msg_CRT ("protected type", N);
- goto Leave;
+
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, Def_Id);
+ end if;
+
+ return;
end if;
Tasking_Used := True;
@@ -1205,6 +1210,13 @@ package body Sem_Ch9 is
Set_Is_Constrained (T, not Has_Discriminants (T));
+ -- If aspects are present, analyze them now. They can make references
+ -- to the discriminants of the type, but not to any components.
+
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, Def_Id);
+ end if;
+
Analyze (Protected_Definition (N));
-- In the case where the protected type is declared at a nested level
@@ -1287,11 +1299,6 @@ package body Sem_Ch9 is
Process_Full_View (N, T, Def_Id);
end if;
end if;
-
- <<Leave>>
- if Has_Aspects (N) then
- Analyze_Aspect_Specifications (N, Def_Id);
- end if;
end Analyze_Protected_Type_Declaration;
---------------------
@@ -2046,6 +2053,10 @@ package body Sem_Ch9 is
Set_Is_Constrained (T, not Has_Discriminants (T));
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, Def_Id);
+ end if;
+
if Present (Task_Definition (N)) then
Analyze_Task_Definition (Task_Definition (N));
end if;
@@ -2100,10 +2111,6 @@ package body Sem_Ch9 is
Process_Full_View (N, T, Def_Id);
end if;
end if;
-
- if Has_Aspects (N) then
- Analyze_Aspect_Specifications (N, Def_Id);
- end if;
end Analyze_Task_Type_Declaration;
-----------------------------------
diff --git a/gcc/ada/sem_intr.adb b/gcc/ada/sem_intr.adb
index 9203a9af878..26f9ff4a74b 100644
--- a/gcc/ada/sem_intr.adb
+++ b/gcc/ada/sem_intr.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, 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- --
@@ -124,7 +124,7 @@ package body Sem_Intr is
end if;
-- For Import_xxx calls, argument must be static string. A string
- -- literal is legal even in Ada83 mode, where such literals are
+ -- literal is legal even in Ada 83 mode, where such literals are
-- not static.
if Cnam = Name_Import_Address
@@ -317,7 +317,11 @@ package body Sem_Intr is
return;
end if;
- if not Is_Numeric_Type (Underlying_Type (T1)) then
+ -- The type must be fully defined and numeric.
+
+ if No (Underlying_Type (T1))
+ or else not Is_Numeric_Type (Underlying_Type (T1))
+ then
Errint ("intrinsic operator can only apply to numeric types", E, N);
end if;
end Check_Intrinsic_Operator;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 46906943762..40afb8b01b4 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -13762,19 +13762,18 @@ package body Sem_Prag is
Error_Msg_N ("Unchecked_Union must not be tagged", Typ);
return;
- elsif Is_Limited_Type (Typ) then
+ elsif not Has_Discriminants (Typ) then
Error_Msg_N
- ("Unchecked_Union must not be limited record type", Typ);
- Explain_Limited_Type (Typ, Typ);
+ ("Unchecked_Union must have one discriminant", Typ);
return;
- else
- if not Has_Discriminants (Typ) then
- Error_Msg_N
- ("Unchecked_Union must have one discriminant", Typ);
- return;
- end if;
+ -- Note: in previous versions of GNAT we used to check for limited
+ -- types and give an error, but in fact the standard does allow
+ -- Unchecked_Union on limited types, so this check was removed.
+
+ -- Proceed with basic error checks completed
+ else
Discr := First_Discriminant (Typ);
while Present (Discr) loop
if No (Discriminant_Default_Value (Discr)) then
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 9ce5282d5b8..d94a6bfa328 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -64,6 +64,7 @@ with Sem_Elab; use Sem_Elab;
with Sem_Eval; use Sem_Eval;
with Sem_Intr; use Sem_Intr;
with Sem_Util; use Sem_Util;
+with Targparm; use Targparm;
with Sem_Type; use Sem_Type;
with Sem_Warn; use Sem_Warn;
with Sinfo; use Sinfo;
@@ -4874,13 +4875,33 @@ package body Sem_Res is
(Is_Real_Type (Etype (Rop))
and then Expr_Value_R (Rop) = Ureal_0))
then
- -- Specialize the warning message according to the operation
+ -- Specialize the warning message according to the operation.
+ -- The following warnings are for the case
case Nkind (N) is
when N_Op_Divide =>
- Apply_Compile_Time_Constraint_Error
- (N, "division by zero?", CE_Divide_By_Zero,
- Loc => Sloc (Right_Opnd (N)));
+
+ -- For division, we have two cases, for float division
+ -- of an unconstrained float type, on a machine where
+ -- Machine_Overflows is false, we don't get an exception
+ -- at run-time, but rather an infinity or Nan. The Nan
+ -- case is pretty obscure, so just warn about infinities.
+
+ if Is_Floating_Point_Type (Typ)
+ and then not Is_Constrained (Typ)
+ and then not Machine_Overflows_On_Target
+ then
+ Error_Msg_N
+ ("float division by zero, " &
+ "may generate '+'/'- infinity?", Right_Opnd (N));
+
+ -- For all other cases, we get a Constraint_Error
+
+ else
+ Apply_Compile_Time_Constraint_Error
+ (N, "division by zero?", CE_Divide_By_Zero,
+ Loc => Sloc (Right_Opnd (N)));
+ end if;
when N_Op_Rem =>
Apply_Compile_Time_Constraint_Error
@@ -7335,6 +7356,48 @@ package body Sem_Res is
Check_For_Visible_Operator (N, B_Typ);
end if;
+ -- Replace AND by AND THEN, or OR by OR ELSE, if Short_Circuit_And_Or
+ -- is active and the result type is standard Boolean (do not mess with
+ -- ops that return a nonstandard Boolean type, because something strange
+ -- is going on).
+
+ -- Note: you might expect this replacement to be done during expansion,
+ -- but that doesn't work, because when the pragma Short_Circuit_And_Or
+ -- is used, no part of the right operand of an "and" or "or" operator
+ -- should be executed if the left operand would short-circuit the
+ -- evaluation of the corresponding "and then" or "or else". If we left
+ -- the replacement to expansion time, then run-time checks associated
+ -- with such operands would be evaluated unconditionally, due to being
+ -- before the condition prior to the rewriting as short-circuit forms
+ -- during expansion.
+
+ if Short_Circuit_And_Or
+ and then B_Typ = Standard_Boolean
+ and then Nkind_In (N, N_Op_And, N_Op_Or)
+ then
+ if Nkind (N) = N_Op_And then
+ Rewrite (N,
+ Make_And_Then (Sloc (N),
+ Left_Opnd => Relocate_Node (Left_Opnd (N)),
+ Right_Opnd => Relocate_Node (Right_Opnd (N))));
+ Analyze_And_Resolve (N, B_Typ);
+
+ -- Case of OR changed to OR ELSE
+
+ else
+ Rewrite (N,
+ Make_Or_Else (Sloc (N),
+ Left_Opnd => Relocate_Node (Left_Opnd (N)),
+ Right_Opnd => Relocate_Node (Right_Opnd (N))));
+ Analyze_And_Resolve (N, B_Typ);
+ end if;
+
+ -- Return now, since analysis of the rewritten ops will take care of
+ -- other reference bookkeeping and expression folding.
+
+ return;
+ end if;
+
Resolve (Left_Opnd (N), B_Typ);
Resolve (Right_Opnd (N), B_Typ);
diff --git a/gcc/ada/sem_res.ads b/gcc/ada/sem_res.ads
index 361b8651569..42b819186dc 100644
--- a/gcc/ada/sem_res.ads
+++ b/gcc/ada/sem_res.ads
@@ -95,8 +95,8 @@ package Sem_Res is
procedure Ambiguous_Character (C : Node_Id);
-- Give list of candidate interpretations when a character literal cannot
-- be resolved, for example in a (useless) comparison such as 'A' = 'B'.
- -- In Ada95 the literals in question can be of type Character or Wide_
- -- Character. In Ada2005 Wide_Wide_Character is also a candidate. The
+ -- In Ada 95 the literals in question can be of type Character or Wide_
+ -- Character. In Ada 2005 Wide_Wide_Character is also a candidate. The
-- node may also be overloaded with user-defined character types.
procedure Check_Parameterless_Call (N : Node_Id);
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 8c2eeeef65b..c391163ea4b 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -1988,12 +1988,12 @@ package body Sem_Type is
-- Otherwise, the predefined operator has precedence, or if the user-
-- defined operation is directly visible we have a true ambiguity.
- -- If this is a fixed-point multiplication and division in Ada83 mode,
+ -- If this is a fixed-point multiplication and division in Ada 83 mode,
-- exclude the universal_fixed operator, which often causes ambiguities
-- in legacy code.
- -- Ditto in Ada2012, where an ambiguity may arise for an operation on
- -- a partial view that is completed with a fixed point type. See
+ -- Ditto in Ada 2012, where an ambiguity may arise for an operation
+ -- on a partial view that is completed with a fixed point type. See
-- AI05-0020 and AI05-0209. The ambiguity is resolved in favor of the
-- user-defined subprogram so that a client of the package has the
-- same resulution as the body of the package.
@@ -3372,18 +3372,28 @@ package body Sem_Type is
function Valid_Boolean_Arg (T : Entity_Id) return Boolean is
begin
- return Is_Boolean_Type (T)
- or else T = Any_Composite
- or else (Is_Array_Type (T)
- and then T /= Any_String
- and then Number_Dimensions (T) = 1
- and then Is_Boolean_Type (Component_Type (T))
- and then (not Is_Private_Composite (T)
- or else In_Instance)
- and then (not Is_Limited_Composite (T)
- or else In_Instance))
+ if Is_Boolean_Type (T)
or else Is_Modular_Integer_Type (T)
- or else T = Universal_Integer;
+ or else T = Universal_Integer
+ or else T = Any_Composite
+ then
+ return True;
+
+ elsif Is_Array_Type (T)
+ and then T /= Any_String
+ and then Number_Dimensions (T) = 1
+ and then Is_Boolean_Type (Component_Type (T))
+ and then
+ ((not Is_Private_Composite (T)
+ and then not Is_Limited_Composite (T))
+ or else In_Instance
+ or else Available_Full_View_Of_Component (T))
+ then
+ return True;
+
+ else
+ return False;
+ end if;
end Valid_Boolean_Arg;
--------------------------
@@ -3395,10 +3405,12 @@ package body Sem_Type is
if T = Any_Composite then
return False;
+
elsif Is_Discrete_Type (T)
or else Is_Real_Type (T)
then
return True;
+
elsif Is_Array_Type (T)
and then Number_Dimensions (T) = 1
and then Is_Discrete_Type (Component_Type (T))
@@ -3408,6 +3420,14 @@ package body Sem_Type is
or else In_Instance)
then
return True;
+
+ elsif Is_Array_Type (T)
+ and then Number_Dimensions (T) = 1
+ and then Is_Discrete_Type (Component_Type (T))
+ and then Available_Full_View_Of_Component (T)
+ then
+ return True;
+
elsif Is_String_Type (T) then
return True;
else
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 5df84dcf7d7..99667d0b060 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -333,6 +333,19 @@ package body Sem_Util is
end if;
end Apply_Compile_Time_Constraint_Error;
+ --------------------------------------
+ -- Available_Full_View_Of_Component --
+ --------------------------------------
+
+ function Available_Full_View_Of_Component (T : Entity_Id) return Boolean is
+ ST : constant Entity_Id := Scope (T);
+ SCT : constant Entity_Id := Scope (Component_Type (T));
+ begin
+ return In_Open_Scopes (ST)
+ and then In_Open_Scopes (SCT)
+ and then Scope_Depth (ST) >= Scope_Depth (SCT);
+ end Available_Full_View_Of_Component;
+
--------------------------------
-- Bad_Predicated_Subtype_Use --
--------------------------------
@@ -2739,7 +2752,7 @@ package body Sem_Util is
end if;
elsif Is_Entity_Name (A2) then
- return Denotes_Same_Prefix (A2, A1);
+ return Denotes_Same_Prefix (A1 => A2, A2 => A1);
elsif Nkind_In (A1, N_Selected_Component, N_Indexed_Component, N_Slice)
and then
@@ -2993,7 +3006,7 @@ package body Sem_Util is
if not Is_Local_Anonymous_Access (Etype (Expr)) then
-- Handle type conversions introduced for a rename of an
- -- Ada2012 stand-alone object of an anonymous access type.
+ -- Ada 2012 stand-alone object of an anonymous access type.
return Dynamic_Accessibility_Level (Expression (Expr));
end if;
@@ -3012,7 +3025,8 @@ package body Sem_Util is
function Effective_Extra_Accessibility (Id : Entity_Id) return Entity_Id is
begin
if Present (Renamed_Object (Id))
- and then Is_Entity_Name (Renamed_Object (Id)) then
+ and then Is_Entity_Name (Renamed_Object (Id))
+ then
return Effective_Extra_Accessibility (Entity (Renamed_Object (Id)));
end if;
@@ -3896,8 +3910,8 @@ package body Sem_Util is
end if;
end loop;
- -- This loop checks the form of the prefix for an entity,
- -- using recursion to deal with intermediate components.
+ -- This loop checks the form of the prefix for an entity, using
+ -- recursion to deal with intermediate components.
loop
-- Check for Y where Y is an entity
@@ -3909,8 +3923,8 @@ package body Sem_Util is
-- Check for components
elsif
- Nkind_In (Expr, N_Selected_Component, N_Indexed_Component) then
-
+ Nkind_In (Expr, N_Selected_Component, N_Indexed_Component)
+ then
Expr := Prefix (Expr);
Off := True;
@@ -6554,19 +6568,18 @@ package body Sem_Util is
(Is_Object (E)
and then
(Is_Aliased (E)
- or else (Present (Renamed_Object (E))
- and then Is_Aliased_View (Renamed_Object (E)))))
+ or else (Present (Renamed_Object (E))
+ and then Is_Aliased_View (Renamed_Object (E)))))
or else ((Is_Formal (E)
or else Ekind (E) = E_Generic_In_Out_Parameter
or else Ekind (E) = E_Generic_In_Parameter)
and then Is_Tagged_Type (Etype (E)))
- or else (Is_Concurrent_Type (E)
- and then In_Open_Scopes (E))
+ or else (Is_Concurrent_Type (E) and then In_Open_Scopes (E))
- -- Current instance of type, either directly or as rewritten
- -- reference to the current object.
+ -- Current instance of type, either directly or as rewritten
+ -- reference to the current object.
or else (Is_Entity_Name (Original_Node (Obj))
and then Present (Entity (Original_Node (Obj)))
@@ -6575,7 +6588,13 @@ package body Sem_Util is
or else (Is_Type (E) and then E = Current_Scope)
or else (Is_Incomplete_Or_Private_Type (E)
- and then Full_View (E) = Current_Scope);
+ and then Full_View (E) = Current_Scope)
+
+ -- Ada 2012 AI05-0053: the return object of an extended return
+ -- statement is aliased if its type is immutably limited.
+
+ or else (Is_Return_Object (E)
+ and then Is_Immutably_Limited_Type (Etype (E)));
elsif Nkind (Obj) = N_Selected_Component then
return Is_Aliased (Entity (Selector_Name (Obj)));
@@ -7345,6 +7364,34 @@ package body Sem_Util is
end if;
end Is_Fully_Initialized_Variant;
+ ----------------------------
+ -- Is_Inherited_Operation --
+ ----------------------------
+
+ function Is_Inherited_Operation (E : Entity_Id) return Boolean is
+ pragma Assert (Is_Overloadable (E));
+ Kind : constant Node_Kind := Nkind (Parent (E));
+ begin
+ return Kind = N_Full_Type_Declaration
+ or else Kind = N_Private_Extension_Declaration
+ or else Kind = N_Subtype_Declaration
+ or else (Ekind (E) = E_Enumeration_Literal
+ and then Is_Derived_Type (Etype (E)));
+ end Is_Inherited_Operation;
+
+ -------------------------------------
+ -- Is_Inherited_Operation_For_Type --
+ -------------------------------------
+
+ function Is_Inherited_Operation_For_Type
+ (E : Entity_Id;
+ Typ : Entity_Id) return Boolean
+ is
+ begin
+ return Is_Inherited_Operation (E)
+ and then Etype (Parent (E)) = Typ;
+ end Is_Inherited_Operation_For_Type;
+
-----------------
-- Is_Iterator --
-----------------
@@ -7415,33 +7462,6 @@ package body Sem_Util is
end if;
end Is_LHS;
- ----------------------------
- -- Is_Inherited_Operation --
- ----------------------------
-
- function Is_Inherited_Operation (E : Entity_Id) return Boolean is
- Kind : constant Node_Kind := Nkind (Parent (E));
- begin
- pragma Assert (Is_Overloadable (E));
- return Kind = N_Full_Type_Declaration
- or else Kind = N_Private_Extension_Declaration
- or else Kind = N_Subtype_Declaration
- or else (Ekind (E) = E_Enumeration_Literal
- and then Is_Derived_Type (Etype (E)));
- end Is_Inherited_Operation;
-
- -------------------------------------
- -- Is_Inherited_Operation_For_Type --
- -------------------------------------
-
- function Is_Inherited_Operation_For_Type
- (E : Entity_Id; Typ : Entity_Id) return Boolean
- is
- begin
- return Is_Inherited_Operation (E)
- and then Etype (Parent (E)) = Typ;
- end Is_Inherited_Operation_For_Type;
-
-----------------------------
-- Is_Library_Level_Entity --
-----------------------------
@@ -7462,6 +7482,17 @@ package body Sem_Util is
return Enclosing_Dynamic_Scope (E) = Standard_Standard;
end Is_Library_Level_Entity;
+ --------------------------------
+ -- Is_Limited_Class_Wide_Type --
+ --------------------------------
+
+ function Is_Limited_Class_Wide_Type (Typ : Entity_Id) return Boolean is
+ begin
+ return
+ Is_Class_Wide_Type (Typ)
+ and then Is_Limited_Type (Typ);
+ end Is_Limited_Class_Wide_Type;
+
---------------------------------
-- Is_Local_Variable_Reference --
---------------------------------
@@ -7501,7 +7532,7 @@ package body Sem_Util is
Is_Object_Reference (Prefix (N))
or else Is_Access_Type (Etype (Prefix (N)));
- -- In Ada95, a function call is a constant object; a procedure
+ -- In Ada 95, a function call is a constant object; a procedure
-- call is not.
when N_Function_Call =>
@@ -7617,7 +7648,7 @@ package body Sem_Util is
elsif Original_Node (AV) /= AV then
- -- In Ada2012, the explicit dereference may be a rewritten call to a
+ -- In Ada 2012, the explicit dereference may be a rewritten call to a
-- Reference function.
if Ada_Version >= Ada_2012
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 77f26b40e8b..eb3528a1a79 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -94,6 +94,15 @@ package Sem_Util is
-- not end with a ? (this is used when the caller wants to parameterize
-- whether an error or warning is given.
+ function Available_Full_View_Of_Component (T : Entity_Id) return Boolean;
+ -- If at the point of declaration an array type has a private or limited
+ -- component, several array operations are not avaiable on the type, and
+ -- the array type is flagged accordingly. If in the immediate scope of
+ -- the array type the component becomes non-private or non-limited, these
+ -- operations become avaiable. This can happen if the scopes of both types
+ -- are open, and the scope of the array is not outside the scope of the
+ -- component.
+
procedure Bad_Predicated_Subtype_Use
(Msg : String;
N : Node_Id;
@@ -836,8 +845,8 @@ package Sem_Util is
-- by the derived type declaration for type Typ.
function Is_Iterator (Typ : Entity_Id) return Boolean;
- -- AI05-0139-2: Check whether Typ is derived from the predefined interface
- -- Ada.Iterator_Interfaces.Forward_Iterator.
+ -- AI05-0139-2: Check whether Typ is one of the predefined interfaces in
+ -- Ada.Iterator_Interfaces, or it is derived from one.
function Is_LHS (N : Node_Id) return Boolean;
-- Returns True iff N is used as Name in an assignment statement
@@ -846,6 +855,9 @@ package Sem_Util is
-- A library-level declaration is one that is accessible from Standard,
-- i.e. a library unit or an entity declared in a library package.
+ function Is_Limited_Class_Wide_Type (Typ : Entity_Id) return Boolean;
+ -- Determine whether a given arbitrary type is a limited class-wide type
+
function Is_Local_Variable_Reference (Expr : Node_Id) return Boolean;
-- Determines whether Expr is a reference to a variable or IN OUT mode
-- parameter of the current enclosing subprogram.
diff --git a/gcc/ada/sigtramp-ppcvxw.c b/gcc/ada/sigtramp-ppcvxw.c
new file mode 100644
index 00000000000..57a02a7d162
--- /dev/null
+++ b/gcc/ada/sigtramp-ppcvxw.c
@@ -0,0 +1,256 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * S I G T R A M P *
+ * *
+ * Asm Implementation File *
+ * *
+ * Copyright (C) 2011, 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- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
+ * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * As a special exception 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. *
+ * *
+ * In particular, you can freely distribute your programs built with the *
+ * GNAT Pro compiler, including any required library run-time units, using *
+ * any licensing terms of your choosing. See the AdaCore Software License *
+ * for full details. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/**********************************************************
+ * PowerPC-VxWorks version of the __gnat_sigtramp service *
+ **********************************************************/
+
+#include "sigtramp.h"
+
+#include <vxWorks.h>
+#include <arch/../regs.h>
+#include <sigLib.h>
+
+/* ----------------------
+ -- General comments --
+ ----------------------
+
+ Stubs are generated from toplevel asms and .cfi directives, much simpler
+ to use and check for correctness than manual encodings of CFI byte
+ sequences. The general idea is to establish CFA as sigcontext->sc_pregs
+ and state where to find the registers as offsets from there.
+
+ As of today, we support a single stub, providing CFI info for common
+ registers (GPRs, LR, ...). We might need variants with support for floating
+ point or altivec registers as well at some point.
+
+ Checking which variant should apply and getting at sc_pregs is simpler
+ to express in C (we can't use offsetof in toplevel asms and hardcoding
+ constants is not workable with the flurry of VxWorks variants), so this
+ is the choice for our toplevel interface. */
+
+/* -----------------------------------------
+ -- Protypes for our internal asm stubs --
+ -----------------------------------------
+
+ SC_PREGS is always expected to be SIGCONTEXT->sc_pregs. Eventhough our
+ symbols will remain local, the prototype claims "extern" and not
+ "static" to prevent compiler complaints about a symbol used but never
+ defined. */
+
+/* sigtramp stub providing CFI info for common registers. */
+
+extern void __gnat_sigtramp_common
+(int signo, void *siginfo, void *sigcontext,
+ sighandler_t * handler, void * sc_pregs);
+
+
+/* -------------------------------------
+ -- Common interface implementation --
+ -------------------------------------
+
+ We enforce optimization to minimize the overhead of the extra layer. */
+
+void __gnat_sigtramp (int signo, void *si, void *sc,
+ sighandler_t * handler)
+ __attribute__((optimize(2)));
+
+void __gnat_sigtramp (int signo, void *si, void *sc,
+ sighandler_t * handler)
+{
+ struct sigcontext * sctx = (struct sigcontext *) sc;
+
+ __gnat_sigtramp_common (signo, si, sctx, handler, sctx->sc_pregs);
+}
+
+
+/* ---------------------------
+ -- And now the asm stubs --
+ ---------------------------
+
+ They all have a common structure with blocks of asm sequences queued one
+ after the others. Typically:
+
+ SYMBOL_START
+
+ CFI_DIRECTIVES
+ CFI_DEF_CFA,
+ CFI_COMMON_REGISTERS,
+ ...
+
+ STUB_BODY
+ asm code to establish frame, setup the cfa reg value,
+ call the real signal handler, ...
+
+ SYMBOL_END
+*/
+
+/*--------------------------------
+ -- Misc constants and helpers --
+ -------------------------------- */
+
+/* REGNO constants, dwarf column numbers for registers of interest. */
+
+#define REGNO_LR 65
+#define REGNO_XER 76
+#define REGNO_CR 70
+#define REGNO_GR(N) (N)
+
+#define REGNO_PC 67 /* ARG_POINTER_REGNUM */
+
+/* asm string contruction helpers. */
+
+#define STR(TEXT) #TEXT
+/* stringify expanded TEXT, surrounding it with double quotes. */
+
+#define S(E) STR(E)
+/* stringify E, which will resolve as text but may contain macros
+ still to be expanded. */
+
+/* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
+ multine contents: */
+#define TAB(S) "\t" S
+#define CR(S) S "\n"
+#define TCR(S) TAB(CR(S))
+
+/*------------------------------
+ -- Stub construction blocks --
+ ------------------------------ */
+
+/* CFA setup block
+ ---------------
+ Only non-volatile registers are suitable for a CFA base. We use r14
+ here and set it to the value we need in stub body that follows. */
+
+#define CFI_DEF_CFA \
+CR(".cfi_def_cfa 14, 0")
+
+/* Register location blocks
+ ------------------------
+ Rules to find registers of interest from the CFA. This should
+ comprise all the non-volatile registers relevant to the interrupted
+ context. */
+
+#define COMMON_CFI(REG) \
+ ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
+
+#define CFI_COMMON_REGS \
+CR("# CFI for common registers\n") \
+TCR(COMMON_CFI(GR(1))) \
+TCR(COMMON_CFI(GR(14))) \
+TCR(COMMON_CFI(GR(15))) \
+TCR(COMMON_CFI(GR(16))) \
+TCR(COMMON_CFI(GR(17))) \
+TCR(COMMON_CFI(GR(18))) \
+TCR(COMMON_CFI(GR(19))) \
+TCR(COMMON_CFI(GR(20))) \
+TCR(COMMON_CFI(GR(21))) \
+TCR(COMMON_CFI(GR(22))) \
+TCR(COMMON_CFI(GR(23))) \
+TCR(COMMON_CFI(GR(24))) \
+TCR(COMMON_CFI(GR(25))) \
+TCR(COMMON_CFI(GR(26))) \
+TCR(COMMON_CFI(GR(27))) \
+TCR(COMMON_CFI(GR(28))) \
+TCR(COMMON_CFI(GR(29))) \
+TCR(COMMON_CFI(GR(30))) \
+TCR(COMMON_CFI(GR(31))) \
+TCR(COMMON_CFI(LR)) \
+TCR(COMMON_CFI(CR)) \
+TCR(COMMON_CFI(PC)) \
+TCR(".cfi_return_column " S(REGNO_PC))
+
+/* Trampoline body block
+ --------------------- */
+
+#define SIGTRAMP_BODY \
+CR("") \
+TCR("# Allocate frame and save the non-volatile") \
+TCR("# registers we're going to modify") \
+TCR("stwu %r1,-16(%r1)") \
+TCR("mflr %r0") \
+TCR("stw %r0,20(%r1)") \
+TCR("stw %r14,8(%r1)") \
+TCR("") \
+TCR("# Setup r14 = sc_pregs, that we'll retrieve as our CFA value") \
+TCR("mr %r14, %r7") \
+TCR("") \
+TCR("# Call the real handler. The signo, siginfo and sigcontext") \
+TCR("# arguments are the same as those we received in r3, r4 and r5") \
+TCR("mtctr %r6") \
+TCR("bctrl") \
+TCR("") \
+TCR("# Restore our callee-saved items, release our frame and return") \
+TCR("lwz %r14,8(%r1)") \
+TCR("lwz %r0,20(%r1)") \
+TCR("mtlr %r0") \
+TCR("") \
+TCR("addi %r1,%r1,16") \
+TCR("blr")
+
+/* Symbol definition block
+ ----------------------- */
+
+#define SIGTRAMP_START(SYM) \
+CR("# " S(SYM) " cfi trampoline") \
+TCR(".type " S(SYM) ", @function") \
+CR("") \
+CR(S(SYM) ":") \
+TCR(".cfi_startproc") \
+TCR(".cfi_signal_frame")
+
+/* Symbol termination block
+ ------------------------ */
+
+#define SIGTRAMP_END(SYM) \
+CR(".cfi_endproc") \
+TCR(".size " S(SYM) ", .-" S(SYM))
+
+/*----------------------------
+ -- And now, the real code --
+ ---------------------------- */
+
+/* Text section start. The compiler isn't aware of that switch. */
+
+asm (".text\n"
+ TCR(".align 2"));
+
+/* sigtramp stub for common registers. */
+
+#define TRAMP_COMMON __gnat_sigtramp_common
+
+asm (SIGTRAMP_START(TRAMP_COMMON));
+asm (CFI_DEF_CFA);
+asm (CFI_COMMON_REGS);
+asm (SIGTRAMP_BODY);
+asm (SIGTRAMP_END(TRAMP_COMMON));
+
+
diff --git a/gcc/ada/sigtramp.h b/gcc/ada/sigtramp.h
new file mode 100644
index 00000000000..5e3cc5b77c9
--- /dev/null
+++ b/gcc/ada/sigtramp.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * S I G T R A M P *
+ * *
+ * C Header File *
+ * *
+ * Copyright (C) 2011, 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- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
+ * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * As a special exception 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. *
+ * *
+ * In particular, you can freely distribute your programs built with the *
+ * GNAT Pro compiler, including any required library run-time units, using *
+ * any licensing terms of your choosing. See the AdaCore Software License *
+ * for full details. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* On targets where this is implemented, we resort to a signal handler
+ trampoline to set-up the DWARF Call Frame Information that let unwinders
+ walk through the signal frame up into the interrupted application code.
+ This file introduces the relevant declarations. */
+
+/* This file should only be #included on targets that do implement the
+ trampoline, which needs to expose the following interface: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef void sighandler_t (int signo, void *siginfo, void *sigcontext);
+
+ void __gnat_sigtramp (int signo, void *siginfo, void *sigcontext,
+ sighandler_t * handler);
+
+ /* To be called from an established signal handler. Setup the DWARF CFI
+ bits letting unwinders walk through the signal frame up into the
+ interrupted application code, and then call HANDLER (SIGNO, SIGINFO,
+ SIGCONTEXT). */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index 696630ec298..4d383fd0608 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -911,8 +911,7 @@ __gnat_get_task_options (void)
/* Force VX_FP_TASK because it is almost always required */
options |= VX_FP_TASK;
-#if defined (__SPE__) && (! defined (__VXWORKSMILS__)) \
- && (! defined (VTHREADS))
+#if defined (__SPE__) && (! defined (__VXWORKSMILS__))
options |= VX_SPE_TASK;
#endif
diff --git a/gcc/ada/vms_data.ads b/gcc/ada/vms_data.ads
index 1da9855245a..bfda0a73c56 100644
--- a/gcc/ada/vms_data.ads
+++ b/gcc/ada/vms_data.ads
@@ -6119,6 +6119,30 @@ package VMS_Data is
-- See 'HELP GNAT COMPILE /WIDE_CHARACTER_ENCODING' for an explanation
-- about the different character encoding methods.
+ S_Pretty_Enums : aliased constant S := "/ENUM_CASING=" &
+ "AS_DECLARED " &
+ "-neD " &
+ "LOWER_CASE " &
+ "-neL " &
+ "UPPER_CASE " &
+ "-neU " &
+ "MIXED_CASE " &
+ "-neM";
+ -- /ENUM_CASING=name-option
+ --
+ -- Specify the casing of enumeration literals. If not specified, the
+ -- casing of enumeration literals is defined by the NAME_CASING option.
+ -- 'name-option' may be one of:
+ --
+ -- AS_DECLARED Literals casing for defining occurrences are
+ -- as they appear in the source file.
+ --
+ -- LOWER_CASE Literals are in lower case.
+ --
+ -- UPPER_CASE Literals are in upper case.
+ --
+ -- MIXED_CASE Literals are in mixed case.
+
S_Pretty_Files : aliased constant S := "/FILES=@" &
"-files=@";
-- /FILES=filename
@@ -6369,6 +6393,7 @@ package VMS_Data is
S_Pretty_Eol 'Access,
S_Pretty_Ext 'Access,
S_Pretty_Encoding 'Access,
+ S_Pretty_Enums 'Access,
S_Pretty_Files 'Access,
S_Pretty_Follow 'Access,
S_Pretty_Forced 'Access,
diff --git a/gcc/builtins.c b/gcc/builtins.c
index b79ce6f4a74..296c5b7dd91 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -75,11 +75,7 @@ const char * built_in_names[(int) END_BUILTINS] =
/* Setup an array of _DECL trees, make sure each element is
initialized to NULL_TREE. */
-tree built_in_decls[(int) END_BUILTINS];
-/* Declarations used when constructing the builtin implicitly in the compiler.
- It may be NULL_TREE when this is invalid (for instance runtime is not
- required to implement the function call in all cases). */
-tree implicit_built_in_decls[(int) END_BUILTINS];
+builtin_info_type builtin_info;
static const char *c_getstr (tree);
static rtx c_readstr (const char *, enum machine_mode);
@@ -1791,17 +1787,15 @@ expand_builtin_classify_type (tree exp)
fcode = BUILT_IN_MATHFN##_R; fcodef = BUILT_IN_MATHFN##F_R ; \
fcodel = BUILT_IN_MATHFN##L_R ; break;
-/* Return mathematic function equivalent to FN but operating directly
- on TYPE, if available. If IMPLICIT is true find the function in
- implicit_built_in_decls[], otherwise use built_in_decls[]. If we
- can't do the conversion, return zero. */
+/* Return mathematic function equivalent to FN but operating directly on TYPE,
+ if available. If IMPLICIT is true use the implicit builtin declaration,
+ otherwise use the explicit declaration. If we can't do the conversion,
+ return zero. */
static tree
-mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
+mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit_p)
{
- tree const *const fn_arr
- = implicit ? implicit_built_in_decls : built_in_decls;
- enum built_in_function fcode, fcodef, fcodel;
+ enum built_in_function fcode, fcodef, fcodel, fcode2;
switch (fn)
{
@@ -1898,13 +1892,18 @@ mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit)
}
if (TYPE_MAIN_VARIANT (type) == double_type_node)
- return fn_arr[fcode];
+ fcode2 = fcode;
else if (TYPE_MAIN_VARIANT (type) == float_type_node)
- return fn_arr[fcodef];
+ fcode2 = fcodef;
else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
- return fn_arr[fcodel];
+ fcode2 = fcodel;
else
return NULL_TREE;
+
+ if (implicit_p && !builtin_decl_implicit_p (fcode2))
+ return NULL_TREE;
+
+ return builtin_decl_explicit (fcode2);
}
/* Like mathfn_built_in_1(), but always use the implicit array. */
@@ -2554,11 +2553,11 @@ expand_builtin_cexpi (tree exp, rtx target)
rtx op1a, op2a;
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
- fn = built_in_decls[BUILT_IN_SINCOSF];
+ fn = builtin_decl_explicit (BUILT_IN_SINCOSF);
else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
- fn = built_in_decls[BUILT_IN_SINCOS];
+ fn = builtin_decl_explicit (BUILT_IN_SINCOS);
else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
- fn = built_in_decls[BUILT_IN_SINCOSL];
+ fn = builtin_decl_explicit (BUILT_IN_SINCOSL);
else
gcc_unreachable ();
@@ -2580,11 +2579,11 @@ expand_builtin_cexpi (tree exp, rtx target)
tree ctype = build_complex_type (type);
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIF)
- fn = built_in_decls[BUILT_IN_CEXPF];
+ fn = builtin_decl_explicit (BUILT_IN_CEXPF);
else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPI)
- fn = built_in_decls[BUILT_IN_CEXP];
+ fn = builtin_decl_explicit (BUILT_IN_CEXP);
else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL)
- fn = built_in_decls[BUILT_IN_CEXPL];
+ fn = builtin_decl_explicit (BUILT_IN_CEXPL);
else
gcc_unreachable ();
@@ -3129,9 +3128,9 @@ expand_builtin_mempcpy_args (tree dest, tree src, tree len,
rtx target, enum machine_mode mode, int endp)
{
/* If return value is ignored, transform mempcpy into memcpy. */
- if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY])
+ if (target == const0_rtx && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
{
- tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
dest, src, len);
return expand_expr (result, target, mode, EXPAND_NORMAL);
@@ -3292,9 +3291,9 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
src = CALL_EXPR_ARG (exp, 1);
/* If return value is ignored, transform stpcpy into strcpy. */
- if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY])
+ if (target == const0_rtx && builtin_decl_implicit (BUILT_IN_STRCPY))
{
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
tree result = build_call_nofold_loc (loc, fn, 2, dst, src);
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
@@ -4353,7 +4352,7 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
expression to exit or longjmp. */
gimplify_and_add (valist, pre_p);
t = build_call_expr_loc (loc,
- implicit_built_in_decls[BUILT_IN_TRAP], 0);
+ builtin_decl_implicit (BUILT_IN_TRAP), 0);
gimplify_and_add (t, pre_p);
/* This is dead code, but go ahead and finish so that the
@@ -4516,20 +4515,33 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate)
{
rtx op0;
rtx result;
+ bool valid_arglist;
+ unsigned int align;
+ bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
+ == BUILT_IN_ALLOCA_WITH_ALIGN);
/* Emit normal call if marked not-inlineable. */
if (CALL_CANNOT_INLINE_P (exp))
return NULL_RTX;
- if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
+ valid_arglist
+ = (alloca_with_align
+ ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
+ : validate_arglist (exp, INTEGER_TYPE, VOID_TYPE));
+
+ if (!valid_arglist)
return NULL_RTX;
/* Compute the argument. */
op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+ /* Compute the alignment. */
+ align = (alloca_with_align
+ ? TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1))
+ : BIGGEST_ALIGNMENT);
+
/* Allocate the desired space. */
- result = allocate_dynamic_stack_space (op0, 0, BIGGEST_ALIGNMENT,
- cannot_accumulate);
+ result = allocate_dynamic_stack_space (op0, 0, align, cannot_accumulate);
result = convert_memory_address (ptr_mode, result);
return result;
@@ -5113,7 +5125,7 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
if (warned_f_a_n)
break;
- fndecl = implicit_built_in_decls[BUILT_IN_SYNC_FETCH_AND_NAND_N];
+ fndecl = builtin_decl_implicit (BUILT_IN_SYNC_FETCH_AND_NAND_N);
inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
warned_f_a_n = true;
break;
@@ -5127,7 +5139,7 @@ expand_builtin_sync_operation (enum machine_mode mode, tree exp,
if (warned_n_a_f)
break;
- fndecl = implicit_built_in_decls[BUILT_IN_SYNC_NAND_AND_FETCH_N];
+ fndecl = builtin_decl_implicit (BUILT_IN_SYNC_NAND_AND_FETCH_N);
inform (loc, "%qD changed semantics in GCC 4.4", fndecl);
warned_n_a_f = true;
break;
@@ -5304,6 +5316,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
&& !called_as_built_in (fndecl)
&& DECL_ASSEMBLER_NAME_SET_P (fndecl)
&& fcode != BUILT_IN_ALLOCA
+ && fcode != BUILT_IN_ALLOCA_WITH_ALIGN
&& fcode != BUILT_IN_FREE)
return expand_call (exp, target, ignore);
@@ -5559,6 +5572,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
/* If the allocation stems from the declaration of a variable-sized
object, it cannot accumulate. */
target = expand_builtin_alloca (exp, CALL_ALLOCA_FOR_VAR_P (exp));
@@ -6232,7 +6246,7 @@ build_builtin_expect_predicate (location_t loc, tree pred, tree expected)
{
tree fn, arg_types, pred_type, expected_type, call_expr, ret_type;
- fn = built_in_decls[BUILT_IN_EXPECT];
+ fn = builtin_decl_explicit (BUILT_IN_EXPECT);
arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
ret_type = TREE_TYPE (TREE_TYPE (fn));
pred_type = TREE_VALUE (arg_types);
@@ -8024,7 +8038,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
&& (MIN (src_align, dest_align) / BITS_PER_UNIT
>= (unsigned HOST_WIDE_INT) tree_low_cst (len, 1))))
{
- tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
if (!fn)
return NULL_TREE;
return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8083,7 +8097,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
else
return NULL_TREE;
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
if (!fn)
return NULL_TREE;
return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8102,7 +8116,7 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
if (!refs_may_alias_p_1 (&destr, &srcr, false))
{
tree fn;
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
if (!fn)
return NULL_TREE;
return build_call_expr_loc (loc, fn, 3, dest, src, len);
@@ -8277,7 +8291,7 @@ fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
if (optimize_function_for_size_p (cfun))
return NULL_TREE;
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
if (!fn)
return NULL_TREE;
@@ -8288,7 +8302,8 @@ fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len)
return NULL_TREE;
}
- len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
+ len = fold_convert_loc (loc, size_type_node, len);
+ len = size_binop_loc (loc, PLUS_EXPR, len, build_int_cst (size_type_node, 1));
return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
build_call_expr_loc (loc, fn, 3, dest, src, len));
}
@@ -8315,11 +8330,13 @@ fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src)
&& !integer_zerop (len))
return NULL_TREE;
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
if (!fn)
return NULL_TREE;
- lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
+ lenp1 = size_binop_loc (loc, PLUS_EXPR,
+ fold_convert_loc (loc, size_type_node, len),
+ build_int_cst (size_type_node, 1));
/* We use dest twice in building our expression. Save it from
multiple expansions. */
dest = builtin_save_expr (dest);
@@ -8372,9 +8389,11 @@ fold_builtin_strncpy (location_t loc, tree fndecl, tree dest,
return NULL_TREE;
/* OK transform into builtin memcpy. */
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
if (!fn)
return NULL_TREE;
+
+ len = fold_convert_loc (loc, size_type_node, len);
return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
build_call_expr_loc (loc, fn, 3, dest, src, len));
}
@@ -9193,7 +9212,7 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
CASE_FLT_FN (BUILT_IN_ISINF):
{
/* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
- tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
+ tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER);
tree const type = TREE_TYPE (arg);
REAL_VALUE_TYPE r;
char buf[128];
@@ -9209,7 +9228,7 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
case BUILT_IN_ISFINITE:
{
/* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
- tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
+ tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
tree const type = TREE_TYPE (arg);
REAL_VALUE_TYPE r;
char buf[128];
@@ -9232,8 +9251,8 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg)
{
/* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
islessequal(fabs(x),DBL_MAX). */
- tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
- tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
+ tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL);
+ tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL);
tree const type = TREE_TYPE (arg);
REAL_VALUE_TYPE rmax, rmin;
char buf[128];
@@ -9294,7 +9313,7 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
1. So e.g. "if (isinf_sign(x))" would be folded to just
"if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */
tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0);
- tree isinf_fn = built_in_decls[BUILT_IN_ISINF];
+ tree isinf_fn = builtin_decl_explicit (BUILT_IN_ISINF);
tree tmp = NULL_TREE;
arg = builtin_save_expr (arg);
@@ -10017,7 +10036,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
case BUILT_IN_STPCPY:
if (ignore)
{
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
if (!fn)
break;
@@ -10355,7 +10374,7 @@ fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
might not be performed. */
-static bool
+bool
avoid_folding_inline_builtin (tree fndecl)
{
return (DECL_DECLARED_INLINE_P (fndecl)
@@ -10817,7 +10836,7 @@ fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
if (p2[1] != '\0')
return NULL_TREE;
- fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+ fn = builtin_decl_implicit (BUILT_IN_STRCHR);
if (!fn)
return NULL_TREE;
@@ -10937,7 +10956,7 @@ fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
if (! integer_zerop (s2))
return NULL_TREE;
- fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+ fn = builtin_decl_implicit (BUILT_IN_STRCHR);
if (!fn)
return NULL_TREE;
@@ -11001,7 +11020,7 @@ fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
if (p2[1] != '\0')
return NULL_TREE; /* Really call strpbrk. */
- fn = implicit_built_in_decls[BUILT_IN_STRCHR];
+ fn = builtin_decl_implicit (BUILT_IN_STRCHR);
if (!fn)
return NULL_TREE;
@@ -11048,8 +11067,8 @@ fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
{
/* See if we can store by pieces into (dst + strlen(dst)). */
tree newdst, call;
- tree strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
- tree strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
+ tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
if (!strlen_fn || !strcpy_fn)
return NULL_TREE;
@@ -11122,7 +11141,7 @@ fold_builtin_strncat (location_t loc, tree dst, tree src, tree len)
if (TREE_CODE (len) == INTEGER_CST && p
&& compare_tree_int (len, strlen (p)) >= 0)
{
- tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
+ tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
/* If the replacement _DECL isn't initialized, don't do the
transformation. */
@@ -11227,7 +11246,7 @@ fold_builtin_strcspn (location_t loc, tree s1, tree s2)
/* If the second argument is "", return __builtin_strlen(s1). */
if (p2 && *p2 == '\0')
{
- tree fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+ tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
/* If the replacement _DECL isn't initialized, don't do the
transformation. */
@@ -11253,10 +11272,12 @@ fold_builtin_fputs (location_t loc, tree arg0, tree arg1,
{
/* If we're using an unlocked function, assume the other unlocked
functions exist explicitly. */
- tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_FPUTC];
- tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_FWRITE];
+ tree const fn_fputc = (unlocked
+ ? builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED)
+ : builtin_decl_implicit (BUILT_IN_FPUTC));
+ tree const fn_fwrite = (unlocked
+ ? builtin_decl_explicit (BUILT_IN_FWRITE_UNLOCKED)
+ : builtin_decl_implicit (BUILT_IN_FWRITE));
/* If the return value is used, don't do the transformation. */
if (!ignore)
@@ -11450,7 +11471,7 @@ fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
/* If the format doesn't contain % args or %%, use strcpy. */
if (strchr (fmt_str, target_percent) == NULL)
{
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
if (!fn)
return NULL_TREE;
@@ -11470,7 +11491,7 @@ fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
{
tree fn;
- fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ fn = builtin_decl_implicit (BUILT_IN_STRCPY);
if (!fn)
return NULL_TREE;
@@ -11492,7 +11513,7 @@ fold_builtin_sprintf (location_t loc, tree dest, tree fmt,
if (call && retval)
{
retval = fold_convert_loc
- (loc, TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
+ (loc, TREE_TYPE (TREE_TYPE (builtin_decl_implicit (BUILT_IN_SPRINTF))),
retval);
return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
}
@@ -11545,7 +11566,7 @@ fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
/* If the format doesn't contain % args or %%, use strcpy. */
if (strchr (fmt_str, target_percent) == NULL)
{
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
size_t len = strlen (fmt_str);
/* Don't optimize snprintf (buf, 4, "abc", ptr++). */
@@ -11577,7 +11598,7 @@ fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
/* If the format is "%s", use strcpy if the result isn't used. */
else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
{
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ tree fn = builtin_decl_implicit (BUILT_IN_STRCPY);
unsigned HOST_WIDE_INT origlen;
/* Don't crash on snprintf (str1, cst, "%s"). */
@@ -11612,7 +11633,7 @@ fold_builtin_snprintf (location_t loc, tree dest, tree destsize, tree fmt,
if (call && retval)
{
- tree fn = built_in_decls[BUILT_IN_SNPRINTF];
+ tree fn = builtin_decl_explicit (BUILT_IN_SNPRINTF);
retval = fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fn)), retval);
return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
}
@@ -11700,16 +11721,16 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
switch (fcode)
{
case BUILT_IN_MEMCPY_CHK:
- fn = built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
break;
case BUILT_IN_MEMPCPY_CHK:
- fn = built_in_decls[BUILT_IN_MEMPCPY];
+ fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
break;
case BUILT_IN_MEMMOVE_CHK:
- fn = built_in_decls[BUILT_IN_MEMMOVE];
+ fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
break;
case BUILT_IN_MEMSET_CHK:
- fn = built_in_decls[BUILT_IN_MEMSET];
+ fn = builtin_decl_explicit (BUILT_IN_MEMSET);
break;
default:
break;
@@ -11761,7 +11782,7 @@ expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
normal __memcpy_chk. */
if (readonly_data_expr (src))
{
- tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ tree fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
if (!fn)
return NULL_RTX;
fn = build_call_nofold_loc (EXPR_LOCATION (exp), fn, 4,
@@ -12025,7 +12046,7 @@ fold_builtin_memory_chk (location_t loc, tree fndecl,
{
/* (void) __mempcpy_chk () can be optimized into
(void) __memcpy_chk (). */
- fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
if (!fn)
return NULL_TREE;
@@ -12047,16 +12068,16 @@ fold_builtin_memory_chk (location_t loc, tree fndecl,
switch (fcode)
{
case BUILT_IN_MEMCPY_CHK:
- fn = built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
break;
case BUILT_IN_MEMPCPY_CHK:
- fn = built_in_decls[BUILT_IN_MEMPCPY];
+ fn = builtin_decl_explicit (BUILT_IN_MEMPCPY);
break;
case BUILT_IN_MEMMOVE_CHK:
- fn = built_in_decls[BUILT_IN_MEMMOVE];
+ fn = builtin_decl_explicit (BUILT_IN_MEMMOVE);
break;
case BUILT_IN_MEMSET_CHK:
- fn = built_in_decls[BUILT_IN_MEMSET];
+ fn = builtin_decl_explicit (BUILT_IN_MEMSET);
break;
default:
break;
@@ -12111,7 +12132,7 @@ fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
/* If return value of __stpcpy_chk is ignored,
optimize into __strcpy_chk. */
- fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
if (!fn)
return NULL_TREE;
@@ -12123,11 +12144,13 @@ fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
/* If c_strlen returned something, but not a constant,
transform __strcpy_chk into __memcpy_chk. */
- fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
if (!fn)
return NULL_TREE;
- len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
+ len = fold_convert_loc (loc, size_type_node, len);
+ len = size_binop_loc (loc, PLUS_EXPR, len,
+ build_int_cst (size_type_node, 1));
return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)),
build_call_expr_loc (loc, fn, 4,
dest, src, len, size));
@@ -12141,8 +12164,8 @@ fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest,
}
/* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
- fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
- ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
+ fn = builtin_decl_explicit (fcode == BUILT_IN_STPCPY_CHK
+ ? BUILT_IN_STPCPY : BUILT_IN_STRCPY);
if (!fn)
return NULL_TREE;
@@ -12186,7 +12209,7 @@ fold_builtin_strncpy_chk (location_t loc, tree dest, tree src,
}
/* If __builtin_strncpy_chk is used, assume strncpy is available. */
- fn = built_in_decls[BUILT_IN_STRNCPY];
+ fn = builtin_decl_explicit (BUILT_IN_STRNCPY);
if (!fn)
return NULL_TREE;
@@ -12217,7 +12240,7 @@ fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest,
return NULL_TREE;
/* If __builtin_strcat_chk is used, assume strcat is available. */
- fn = built_in_decls[BUILT_IN_STRCAT];
+ fn = builtin_decl_explicit (BUILT_IN_STRCAT);
if (!fn)
return NULL_TREE;
@@ -12259,7 +12282,7 @@ fold_builtin_strncat_chk (location_t loc, tree fndecl,
&& ! tree_int_cst_lt (len, src_len))
{
/* If LEN >= strlen (SRC), optimize into __strcat_chk. */
- fn = built_in_decls[BUILT_IN_STRCAT_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_STRCAT_CHK);
if (!fn)
return NULL_TREE;
@@ -12269,7 +12292,7 @@ fold_builtin_strncat_chk (location_t loc, tree fndecl,
}
/* If __builtin_strncat_chk is used, assume strncat is available. */
- fn = built_in_decls[BUILT_IN_STRNCAT];
+ fn = builtin_decl_explicit (BUILT_IN_STRNCAT);
if (!fn)
return NULL_TREE;
@@ -12360,8 +12383,8 @@ fold_builtin_sprintf_chk_1 (location_t loc, int nargs, tree *args,
}
/* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
- fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
- ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
+ fn = builtin_decl_explicit (fcode == BUILT_IN_VSPRINTF_CHK
+ ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF);
if (!fn)
return NULL_TREE;
@@ -12449,8 +12472,8 @@ fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
/* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
available. */
- fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
- ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
+ fn = builtin_decl_explicit (fcode == BUILT_IN_VSNPRINTF_CHK
+ ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF);
if (!fn)
return NULL_TREE;
@@ -12504,13 +12527,13 @@ fold_builtin_printf (location_t loc, tree fndecl, tree fmt,
{
/* If we're using an unlocked function, assume the other
unlocked functions exist explicitly. */
- fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
- fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
+ fn_putchar = builtin_decl_explicit (BUILT_IN_PUTCHAR_UNLOCKED);
+ fn_puts = builtin_decl_explicit (BUILT_IN_PUTS_UNLOCKED);
}
else
{
- fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
- fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
+ fn_putchar = builtin_decl_implicit (BUILT_IN_PUTCHAR);
+ fn_puts = builtin_decl_implicit (BUILT_IN_PUTS);
}
if (!init_target_chars ())
@@ -12655,13 +12678,13 @@ fold_builtin_fprintf (location_t loc, tree fndecl, tree fp,
{
/* If we're using an unlocked function, assume the other
unlocked functions exist explicitly. */
- fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
- fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
+ fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED);
+ fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED);
}
else
{
- fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
- fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
+ fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC);
+ fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS);
}
if (!init_target_chars ())
@@ -13463,7 +13486,7 @@ fold_call_stmt (gimple stmt, bool ignore)
return NULL_TREE;
}
-/* Look up the function in built_in_decls that corresponds to DECL
+/* Look up the function in builtin_decl that corresponds to DECL
and set ASMSPEC as its user assembler name. DECL must be a
function decl that declares a builtin. */
@@ -13475,8 +13498,9 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec)
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
&& asmspec != 0);
- builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
- set_user_assembler_name (builtin, asmspec);
+ builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
+ set_user_assembler_name (
+builtin, asmspec);
switch (DECL_FUNCTION_CODE (decl))
{
case BUILT_IN_MEMCPY:
@@ -13561,6 +13585,7 @@ is_inexpensive_builtin (tree decl)
{
case BUILT_IN_ABS:
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
case BUILT_IN_BSWAP32:
case BUILT_IN_BSWAP64:
case BUILT_IN_CLZ:
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 424f0f1a085..0420b550f3b 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -131,8 +131,8 @@ along with GCC; see the file COPYING3. If not see
define it here at all. */
#undef DEF_BUILTIN_STUB
#define DEF_BUILTIN_STUB(ENUM, NAME) \
- DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, 0, 0, false, false, \
- false, 0, false, false)
+ DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_LAST, BT_LAST, false, false, \
+ false, ATTR_LAST, false, false)
/* Builtin used by the implementation of GNU OpenMP. None of these are
actually implemented in the compiler; they're all in libgomp. */
@@ -173,6 +173,9 @@ along with GCC; see the file COPYING3. If not see
#undef ATTR_MATHFN_FPROUNDING_STORE
#define ATTR_MATHFN_FPROUNDING_STORE ATTR_NOTHROW_LEAF_LIST
+/* Make sure 0 is not a legitimate builtin. */
+DEF_BUILTIN_STUB(BUILT_IN_NONE, (const char *)0)
+
/* Category: math builtins. */
DEF_LIB_BUILTIN (BUILT_IN_ACOS, "acos", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSF, "acosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
@@ -738,6 +741,7 @@ DEF_BUILTIN_STUB (BUILT_IN_SETJMP_RECEIVER, "__builtin_setjmp_receiver")
/* Implementing variable sized local variables. */
DEF_BUILTIN_STUB (BUILT_IN_STACK_SAVE, "__builtin_stack_save")
DEF_BUILTIN_STUB (BUILT_IN_STACK_RESTORE, "__builtin_stack_restore")
+DEF_BUILTIN_STUB (BUILT_IN_ALLOCA_WITH_ALIGN, "__builtin_alloca_with_align")
/* Object size checking builtins. */
DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index cb58d324dca..7af70f00c0f 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -2372,17 +2372,21 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
{
C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
- switch (DECL_FUNCTION_CODE (newdecl))
- {
- /* If a compatible prototype of these builtin functions
- is seen, assume the runtime implements it with the
- expected semantics. */
- case BUILT_IN_STPCPY:
- implicit_built_in_decls[DECL_FUNCTION_CODE (newdecl)]
- = built_in_decls[DECL_FUNCTION_CODE (newdecl)];
- default:
- break;
- }
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+ switch (fncode)
+ {
+ /* If a compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with the
+ expected semantics. */
+ case BUILT_IN_STPCPY:
+ if (builtin_decl_explicit_p (fncode))
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ break;
+ }
+ }
}
else
C_DECL_BUILTIN_PROTOTYPE (newdecl)
@@ -4338,7 +4342,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
}
/* If this is a function and an assembler name is specified, reset DECL_RTL
- so we can give it its new name. Also, update built_in_decls if it
+ so we can give it its new name. Also, update builtin_decl if it
was a normal built-in. */
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 080d42ac340..d0bcf0f87f8 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,80 @@
+2011-10-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50760
+ * c-lex.c (fe_file_change): Use LINEMAP_SYSP when
+ !NO_IMPLICIT_EXTERN_C.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * c-common.c (c_common_reswords): Add __bases,
+ __direct_bases.
+ * c-common.h: Add RID_BASES and RID_DIRECT_BASES.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50757
+ * c.opt ([Wnonnull]): Add C++ and Objective-C++.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * c.opt (fdebug-cpp): New option.
+ * c-opts.c (c_common_handle_option): Handle the option.
+ * c-ppoutput.c (maybe_print_line_1): New static function. Takes an
+ output stream in parameter. Factorized from ...
+ (maybe_print_line): ... this. Dump location debug information when
+ -fdebug-cpp is in effect.
+ (print_line_1): New static function. Takes an output stream in
+ parameter. Factorized from ...
+ (print_line): ... here. Dump location information when -fdebug-cpp
+ is in effect.
+ (scan_translation_unit): Dump location information when
+ -fdebug-cpp is in effect.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * c.opt (ftrack-macro-expansion): New option. Handle it with and
+ without argument.
+ * c-opts.c (c_common_handle_option)<case
+ OPT_ftrack_macro_expansion_, case OPT_ftrack_macro_expansion>: New
+ cases. Handle -ftrack-macro-expansion with and without argument.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * c-ppoutput.c (scan_translation_unit, maybe_print_line)
+ (print_line, cb_define, do_line_change): Adjust to avoid touching
+ the internals of struct line_map. Use the public API instead.
+ * c-pch.c (c_common_read_pch): Likewise.
+ * c-lex.c (fe_file_change): Likewise.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/17212
+ * c.opt ([Wformat-zero-length]): Add C++ and Objective-C++.
+
+2011-10-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/33067
+ * c-pretty-print.c (pp_c_floating_constant): Output
+ max_digits10 (in the ISO C++ WG N1822 sense) decimal digits.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * c-common.c (def_builtin_1): Delete old interface with two
+ parallel arrays to hold standard builtin declarations, and replace
+ it with a function based interface that can support creating
+ builtins on the fly in the future. Change all uses, and poison
+ the old names. Make sure 0 is not a legitimate builtin index.
+ * c-omp.c (c_finish_omp_barrier): Ditto.
+ (c_finish_omp_taskwait): Ditto.
+ (c_finish_omp_flush): Ditto.
+
+2011-10-11 Tristan Gingold <gingold@adacore.com>
+
+ * c.opt: (fallow-parameterless-variadic-functions): New.
+
2011-09-08 Dodji Seketeli <dodji@redhat.com>
PR c++/33255 - Support -Wunused-local-typedefs warning
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index e2852b66328..9d20d80981c 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -423,8 +423,10 @@ const struct c_common_resword c_common_reswords[] =
{ "__asm__", RID_ASM, 0 },
{ "__attribute", RID_ATTRIBUTE, 0 },
{ "__attribute__", RID_ATTRIBUTE, 0 },
+ { "__bases", RID_BASES, D_CXXONLY },
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
{ "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
+ { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, D_CONLY },
{ "__builtin_offsetof", RID_OFFSETOF, 0 },
{ "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
{ "__builtin_va_arg", RID_VA_ARG, 0 },
@@ -433,6 +435,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__const", RID_CONST, 0 },
{ "__const__", RID_CONST, 0 },
{ "__decltype", RID_DECLTYPE, D_CXXONLY },
+ { "__direct_bases", RID_DIRECT_BASES, D_CXXONLY },
{ "__extension__", RID_EXTENSION, 0 },
{ "__func__", RID_C99_FUNCTION_NAME, 0 },
{ "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
@@ -5167,15 +5170,14 @@ def_builtin_1 (enum built_in_function fncode,
decl = add_builtin_function (name, fntype, fncode, fnclass,
(fallback_p ? libname : NULL),
fnattrs);
+
+ set_builtin_decl (fncode, decl, implicit_p);
+
if (both_p
&& !flag_no_builtin && !builtin_function_disabled_p (libname)
&& !(nonansi_p && flag_no_nonansi_builtin))
add_builtin_function (libname, libtype, fncode, fnclass,
NULL, fnattrs);
-
- built_in_decls[(int) fncode] = decl;
- if (implicit_p)
- implicit_built_in_decls[(int) fncode] = decl;
}
/* Nonzero if the type T promotes to int. This is (nearly) the
@@ -9143,11 +9145,13 @@ resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
{
int n = sync_resolve_size (function, params);
tree new_function, first_param, result;
+ enum built_in_function fncode;
if (n == 0)
return error_mark_node;
- new_function = built_in_decls[orig_code + exact_log2 (n) + 1];
+ fncode = (enum built_in_function)((int)orig_code + exact_log2 (n) + 1);
+ new_function = builtin_decl_explicit (fncode);
if (!sync_resolve_params (function, new_function, params))
return error_mark_node;
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index a1f7ebef400..9818c9ca682 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -102,7 +102,7 @@ enum rid
/* C extensions */
RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG,
RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR,
- RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX,
+ RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE,
RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
RID_FRACT, RID_ACCUM,
@@ -128,12 +128,13 @@ enum rid
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
/* C++ extensions */
+ RID_BASES, RID_DIRECT_BASES,
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_VIRTUAL_DESTRUCTOR,
RID_IS_ABSTRACT, RID_IS_BASE_OF,
- RID_IS_CONVERTIBLE_TO, RID_IS_CLASS,
+ RID_IS_CLASS, RID_IS_CONVERTIBLE_TO,
RID_IS_EMPTY, RID_IS_ENUM,
RID_IS_LITERAL_TYPE, RID_IS_POD,
RID_IS_POLYMORPHIC, RID_IS_STD_LAYOUT,
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index e60dcc53588..b151564000c 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -207,11 +207,11 @@ fe_file_change (const struct line_map *new_map)
line = SOURCE_LINE (new_map - 1, included_at);
input_location = new_map->start_location;
- (*debug_hooks->start_source_file) (line, new_map->to_file);
+ (*debug_hooks->start_source_file) (line, LINEMAP_FILE (new_map));
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level)
++c_header_level;
- else if (new_map->sysp == 2)
+ else if (LINEMAP_SYSP (new_map) == 2)
{
c_header_level = 1;
++pending_lang_change;
@@ -224,17 +224,17 @@ fe_file_change (const struct line_map *new_map)
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level && --c_header_level == 0)
{
- if (new_map->sysp == 2)
+ if (LINEMAP_SYSP (new_map) == 2)
warning (0, "badly nested C headers from preprocessor");
--pending_lang_change;
}
#endif
input_location = new_map->start_location;
- (*debug_hooks->end_source_file) (new_map->to_line);
+ (*debug_hooks->end_source_file) (LINEMAP_LINE (new_map));
}
- update_header_times (new_map->to_file);
+ update_header_times (LINEMAP_FILE (new_map));
input_location = new_map->start_location;
}
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 4a5b0ca928b..481211ed72d 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -77,7 +77,7 @@ c_finish_omp_barrier (location_t loc)
{
tree x;
- x = built_in_decls[BUILT_IN_GOMP_BARRIER];
+ x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
x = build_call_expr_loc (loc, x, 0);
add_stmt (x);
}
@@ -91,7 +91,7 @@ c_finish_omp_taskwait (location_t loc)
{
tree x;
- x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+ x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
x = build_call_expr_loc (loc, x, 0);
add_stmt (x);
}
@@ -105,7 +105,7 @@ c_finish_omp_taskyield (location_t loc)
{
tree x;
- x = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+ x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
x = build_call_expr_loc (loc, x, 0);
add_stmt (x);
}
@@ -260,7 +260,7 @@ c_finish_omp_flush (location_t loc)
{
tree x;
- x = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+ x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
x = build_call_expr_loc (loc, x, 0);
add_stmt (x);
}
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 68188da5bce..b211a734200 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -628,6 +628,22 @@ c_common_handle_option (size_t scode, const char *arg, int value,
cpp_opts->preprocessed = value;
break;
+ case OPT_fdebug_cpp:
+ cpp_opts->debug = 1;
+ break;
+
+ case OPT_ftrack_macro_expansion:
+ if (value)
+ value = 2;
+ /* Fall Through. */
+
+ case OPT_ftrack_macro_expansion_:
+ if (arg && *arg != '\0')
+ cpp_opts->track_macro_expansion = value;
+ else
+ cpp_opts->track_macro_expansion = 2;
+ break;
+
case OPT_frepo:
flag_use_repository = value;
if (value)
diff --git a/gcc/c-family/c-ppoutput.c b/gcc/c-family/c-ppoutput.c
index 16d4f7de994..df46ce4c1f5 100644
--- a/gcc/c-family/c-ppoutput.c
+++ b/gcc/c-family/c-ppoutput.c
@@ -59,7 +59,9 @@ static void account_for_newlines (const unsigned char *, size_t);
static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
static void dump_queued_macros (cpp_reader *);
+static void print_line_1 (source_location, const char*, FILE *);
static void print_line (source_location, const char *);
+static void maybe_print_line_1 (source_location, FILE *);
static void maybe_print_line (source_location);
static void do_line_change (cpp_reader *, const cpp_token *,
source_location, int);
@@ -190,9 +192,7 @@ scan_translation_unit (cpp_reader *pfile)
/* Subtle logic to output a space if and only if necessary. */
if (avoid_paste)
{
- const struct line_map *map
- = linemap_lookup (line_table, loc);
- int src_line = SOURCE_LINE (map, loc);
+ int src_line = LOCATION_LINE (loc);
if (print.source == NULL)
print.source = token;
@@ -212,9 +212,7 @@ scan_translation_unit (cpp_reader *pfile)
}
else if (token->flags & PREV_WHITE)
{
- const struct line_map *map
- = linemap_lookup (line_table, loc);
- int src_line = SOURCE_LINE (map, loc);
+ int src_line = LOCATION_LINE (loc);
if (src_line != print.src_line
&& do_line_adjustments
@@ -247,7 +245,12 @@ scan_translation_unit (cpp_reader *pfile)
in_pragma = false;
}
else
- cpp_output_token (token, print.outf);
+ {
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, token->src_loc,
+ print.outf);
+ cpp_output_token (token, print.outf);
+ }
if (token->type == CPP_COMMENT)
account_for_newlines (token->val.str.text, token->val.str.len);
@@ -301,15 +304,17 @@ scan_translation_unit_trad (cpp_reader *pfile)
/* If the token read on logical line LINE needs to be output on a
different line to the current one, output the required newlines or
a line marker, and return 1. Otherwise return 0. */
+
static void
-maybe_print_line (source_location src_loc)
+maybe_print_line_1 (source_location src_loc, FILE *stream)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
- int src_line = SOURCE_LINE (map, src_loc);
+ int src_line = LOCATION_LINE (src_loc);
+ const char *src_file = LOCATION_FILE (src_loc);
+
/* End the previous line of text. */
if (print.printed)
{
- putc ('\n', print.outf);
+ putc ('\n', stream);
print.src_line++;
print.printed = 0;
}
@@ -317,58 +322,87 @@ maybe_print_line (source_location src_loc)
if (!flag_no_line_commands
&& src_line >= print.src_line
&& src_line < print.src_line + 8
- && strcmp (map->to_file, print.src_file) == 0)
+ && strcmp (src_file, print.src_file) == 0)
{
while (src_line > print.src_line)
{
- putc ('\n', print.outf);
+ putc ('\n', stream);
print.src_line++;
}
}
else
- print_line (src_loc, "");
+ print_line_1 (src_loc, "", stream);
+
+}
+
+/* If the token read on logical line LINE needs to be output on a
+ different line to the current one, output the required newlines or
+ a line marker, and return 1. Otherwise return 0. */
+
+static void
+maybe_print_line (source_location src_loc)
+{
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, src_loc,
+ print.outf);
+ maybe_print_line_1 (src_loc, print.outf);
}
/* Output a line marker for logical line LINE. Special flags are "1"
or "2" indicating entering or leaving a file. */
+
static void
-print_line (source_location src_loc, const char *special_flags)
+print_line_1 (source_location src_loc, const char *special_flags, FILE *stream)
{
/* End any previous line of text. */
if (print.printed)
- putc ('\n', print.outf);
+ putc ('\n', stream);
print.printed = 0;
if (!flag_no_line_commands)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
-
- size_t to_file_len = strlen (map->to_file);
+ const char *file_path = LOCATION_FILE (src_loc);
+ int sysp;
+ size_t to_file_len = strlen (file_path);
unsigned char *to_file_quoted =
(unsigned char *) alloca (to_file_len * 4 + 1);
unsigned char *p;
- print.src_line = SOURCE_LINE (map, src_loc);
- print.src_file = map->to_file;
+ print.src_line = LOCATION_LINE (src_loc);
+ print.src_file = file_path;
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
- (const unsigned char *) map->to_file, to_file_len);
+ (const unsigned char *) file_path,
+ to_file_len);
*p = '\0';
- fprintf (print.outf, "# %u \"%s\"%s",
+ fprintf (stream, "# %u \"%s\"%s",
print.src_line == 0 ? 1 : print.src_line,
to_file_quoted, special_flags);
- if (map->sysp == 2)
- fputs (" 3 4", print.outf);
- else if (map->sysp == 1)
- fputs (" 3", print.outf);
+ sysp = in_system_header_at (src_loc);
+ if (sysp == 2)
+ fputs (" 3 4", stream);
+ else if (sysp == 1)
+ fputs (" 3", stream);
- putc ('\n', print.outf);
+ putc ('\n', stream);
}
}
+/* Output a line marker for logical line LINE. Special flags are "1"
+ or "2" indicating entering or leaving a file. */
+
+static void
+print_line (source_location src_loc, const char *special_flags)
+{
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, src_loc,
+ print.outf);
+ print_line_1 (src_loc, special_flags, print.outf);
+}
+
/* Helper function for cb_line_change and scan_translation_unit. */
static void
do_line_change (cpp_reader *pfile, const cpp_token *token,
@@ -391,8 +425,7 @@ do_line_change (cpp_reader *pfile, const cpp_token *token,
ought to care. Some things do care; the fault lies with them. */
if (!CPP_OPTION (pfile, traditional))
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
- int spaces = SOURCE_COLUMN (map, src_loc) - 2;
+ int spaces = LOCATION_COLUMN (src_loc) - 2;
print.printed = 1;
while (-- spaces >= 0)
@@ -421,6 +454,8 @@ cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
static void
cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
{
+ const struct line_map *map;
+
maybe_print_line (line);
fputs ("#define ", print.outf);
@@ -432,7 +467,10 @@ cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- if (linemap_lookup (line_table, line)->to_line != 0)
+ linemap_resolve_location (line_table, line,
+ LRK_MACRO_DEFINITION_LOCATION,
+ &map);
+ if (LINEMAP_LINE (map) != 0)
print.src_line++;
}
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 53d39d643d0..91195613ff1 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -1018,8 +1018,20 @@ pp_c_enumeration_constant (c_pretty_printer *pp, tree e)
static void
pp_c_floating_constant (c_pretty_printer *pp, tree r)
{
+ const struct real_format *fmt
+ = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (r)));
+
+ REAL_VALUE_TYPE floating_cst = TREE_REAL_CST (r);
+ bool is_decimal = floating_cst.decimal;
+
+ /* See ISO C++ WG N1822. Note: The fraction 643/2136 approximates
+ log10(2) to 7 significant digits. */
+ int max_digits10 = 2 + (is_decimal ? fmt->p : fmt->p * 643L / 2136);
+
real_to_decimal (pp_buffer (pp)->digit_buffer, &TREE_REAL_CST (r),
- sizeof (pp_buffer (pp)->digit_buffer), 0, 1);
+ sizeof (pp_buffer (pp)->digit_buffer),
+ max_digits10, 1);
+
pp_string (pp, pp_buffer(pp)->digit_buffer);
if (TREE_TYPE (r) == float_type_node)
pp_character (pp, 'f');
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index e6ac5dca2ef..bfc1a7c922c 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -396,7 +396,7 @@ C ObjC C++ ObjC++ Var(warn_format_y2k) Warning
Warn about strftime formats yielding 2-digit years
Wformat-zero-length
-C ObjC Var(warn_format_zero_length) Warning
+C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning
Warn about zero-length formats
Wformat=
@@ -510,7 +510,7 @@ C++ ObjC++ Var(warn_nonvdtor) Warning
Warn about non-virtual destructors
Wnonnull
-C ObjC Var(warn_nonnull) Warning
+C ObjC C++ ObjC++ Var(warn_nonnull) Warning
Warn about NULL being passed to argument slots marked as requiring non-NULL
Wnormalized=
@@ -700,6 +700,10 @@ Enforce class member access control semantics
fall-virtual
C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+fallow-parameterless-variadic-functions
+C ObjC Var(flag_allow_parameterless_variadic_functions)
+Allow variadic functions without named parameter
+
falt-external-templates
C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
No longer supported
@@ -739,6 +743,10 @@ fconstexpr-depth=
C++ ObjC++ Joined RejectNegative UInteger Var(max_constexpr_depth) Init(512)
-fconstexpr-depth=<number> Specify maximum constexpr recursion depth
+fdebug-cpp
+C ObjC C++ ObjC++
+Emit debug annotations during preprocessing
+
fdeduce-init-list
C++ ObjC++ Var(flag_deduce_init_list) Init(1)
-fno-deduce-init-list disable deduction of std::initializer_list for a template type parameter from a brace-enclosed initializer-list
@@ -941,6 +949,14 @@ fpreprocessed
C ObjC C++ ObjC++
Treat the input file as already preprocessed
+ftrack-macro-expansion
+C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
+; converted into ftrack-macro-expansion=
+
+ftrack-macro-expansion=
+C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
+-ftrack-macro-expansion=<0|1|2> Track locations of tokens coming from macro expansion and display them in error messages
+
fpretty-templates
C++ ObjC++ Var(flag_pretty_templates) Init(1)
-fno-pretty-templates Do not pretty-print template specializations as the template signature followed by the arguments
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index ff376dfb8ff..af6cc149efc 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -3159,10 +3159,19 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr)
if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
{
struct c_arg_info *ret = build_arg_info ();
- /* Suppress -Wold-style-definition for this case. */
- ret->types = error_mark_node;
- error_at (c_parser_peek_token (parser)->location,
- "ISO C requires a named argument before %<...%>");
+
+ if (flag_allow_parameterless_variadic_functions)
+ {
+ /* F (...) is allowed. */
+ ret->types = NULL_TREE;
+ }
+ else
+ {
+ /* Suppress -Wold-style-definition for this case. */
+ ret->types = error_mark_node;
+ error_at (c_parser_peek_token (parser)->location,
+ "ISO C requires a named argument before %<...%>");
+ }
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
@@ -5989,6 +5998,52 @@ c_parser_alignof_expression (c_parser *parser)
}
}
+/* Helper function to read arguments of builtins which are interfaces
+ for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
+ others. The name of the builtin is passed using BNAME parameter.
+ Function returns true if there were no errors while parsing and
+ stores the arguments in CEXPR_LIST. */
+static bool
+c_parser_get_builtin_args (c_parser *parser, const char *bname,
+ VEC(c_expr_t,gc) **ret_cexpr_list)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ VEC (c_expr_t,gc) *cexpr_list;
+ c_expr_t expr;
+
+ *ret_cexpr_list = NULL;
+ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
+ {
+ error_at (loc, "cannot take address of %qs", bname);
+ return false;
+ }
+
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ {
+ c_parser_consume_token (parser);
+ return true;
+ }
+
+ expr = c_parser_expr_no_commas (parser, NULL);
+ cexpr_list = VEC_alloc (c_expr_t, gc, 1);
+ C_EXPR_APPEND (cexpr_list, expr);
+ while (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ expr = c_parser_expr_no_commas (parser, NULL);
+ C_EXPR_APPEND (cexpr_list, expr);
+ }
+
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return false;
+
+ *ret_cexpr_list = cexpr_list;
+ return true;
+}
+
+
/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
postfix-expression:
@@ -6027,6 +6082,10 @@ c_parser_alignof_expression (c_parser *parser)
assignment-expression )
__builtin_types_compatible_p ( type-name , type-name )
__builtin_complex ( assignment-expression , assignment-expression )
+ __builtin_shuffle ( assignment-expression , assignment-expression )
+ __builtin_shuffle ( assignment-expression ,
+ assignment-expression ,
+ assignment-expression, )
offsetof-member-designator:
identifier
@@ -6047,7 +6106,7 @@ c_parser_alignof_expression (c_parser *parser)
static struct c_expr
c_parser_postfix_expression (c_parser *parser)
{
- struct c_expr expr, e1, e2, e3;
+ struct c_expr expr, e1;
struct c_type_name *t1, *t2;
location_t loc = c_parser_peek_token (parser)->location;;
expr.original_code = ERROR_MARK;
@@ -6333,45 +6392,44 @@ c_parser_postfix_expression (c_parser *parser)
}
break;
case RID_CHOOSE_EXPR:
- c_parser_consume_token (parser);
- if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- {
- expr.value = error_mark_node;
- break;
- }
- loc = c_parser_peek_token (parser)->location;
- e1 = c_parser_expr_no_commas (parser, NULL);
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.value = error_mark_node;
- break;
- }
- e2 = c_parser_expr_no_commas (parser, NULL);
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.value = error_mark_node;
- break;
- }
- e3 = c_parser_expr_no_commas (parser, NULL);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
{
+ VEC (c_expr_t, gc) *cexpr_list;
+ c_expr_t *e1_p, *e2_p, *e3_p;
tree c;
- c = e1.value;
- mark_exp_read (e2.value);
- mark_exp_read (e3.value);
+ c_parser_consume_token (parser);
+ if (!c_parser_get_builtin_args (parser,
+ "__builtin_choose_expr",
+ &cexpr_list))
+ {
+ expr.value = error_mark_node;
+ break;
+ }
+
+ if (VEC_length (c_expr_t, cexpr_list) != 3)
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_choose_expr%>");
+ expr.value = error_mark_node;
+ break;
+ }
+
+ e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+ e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+ e3_p = VEC_index (c_expr_t, cexpr_list, 2);
+
+ c = e1_p->value;
+ mark_exp_read (e2_p->value);
+ mark_exp_read (e3_p->value);
if (TREE_CODE (c) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (c)))
error_at (loc,
"first argument to %<__builtin_choose_expr%> not"
" a constant");
constant_expression_warning (c);
- expr = integer_zerop (c) ? e3 : e2;
+ expr = integer_zerop (c) ? *e3_p : *e2_p;
+ break;
}
- break;
case RID_TYPES_COMPATIBLE_P:
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -6410,57 +6468,99 @@ c_parser_postfix_expression (c_parser *parser)
}
break;
case RID_BUILTIN_COMPLEX:
- c_parser_consume_token (parser);
- if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- {
- expr.value = error_mark_node;
- break;
- }
- loc = c_parser_peek_token (parser)->location;
- e1 = c_parser_expr_no_commas (parser, NULL);
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.value = error_mark_node;
- break;
- }
- e2 = c_parser_expr_no_commas (parser, NULL);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- mark_exp_read (e1.value);
- if (TREE_CODE (e1.value) == EXCESS_PRECISION_EXPR)
- e1.value = convert (TREE_TYPE (e1.value),
- TREE_OPERAND (e1.value, 0));
- mark_exp_read (e2.value);
- if (TREE_CODE (e2.value) == EXCESS_PRECISION_EXPR)
- e2.value = convert (TREE_TYPE (e2.value),
- TREE_OPERAND (e2.value, 0));
- if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1.value))
- || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1.value))
- || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2.value))
- || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2.value)))
- {
- error_at (loc, "%<__builtin_complex%> operand "
- "not of real binary floating-point type");
- expr.value = error_mark_node;
- break;
- }
- if (TYPE_MAIN_VARIANT (TREE_TYPE (e1.value))
- != TYPE_MAIN_VARIANT (TREE_TYPE (e2.value)))
- {
- error_at (loc,
- "%<__builtin_complex%> operands of different types");
- expr.value = error_mark_node;
- break;
- }
- if (!flag_isoc99)
- pedwarn (loc, OPT_pedantic,
- "ISO C90 does not support complex types");
- expr.value = build2 (COMPLEX_EXPR,
- build_complex_type (TYPE_MAIN_VARIANT
- (TREE_TYPE (e1.value))),
- e1.value, e2.value);
- break;
+ {
+ VEC(c_expr_t, gc) *cexpr_list;
+ c_expr_t *e1_p, *e2_p;
+
+ c_parser_consume_token (parser);
+ if (!c_parser_get_builtin_args (parser,
+ "__builtin_complex",
+ &cexpr_list))
+ {
+ expr.value = error_mark_node;
+ break;
+ }
+
+ if (VEC_length (c_expr_t, cexpr_list) != 2)
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_complex%>");
+ expr.value = error_mark_node;
+ break;
+ }
+
+ e1_p = VEC_index (c_expr_t, cexpr_list, 0);
+ e2_p = VEC_index (c_expr_t, cexpr_list, 1);
+
+ mark_exp_read (e1_p->value);
+ if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
+ e1_p->value = convert (TREE_TYPE (e1_p->value),
+ TREE_OPERAND (e1_p->value, 0));
+ mark_exp_read (e2_p->value);
+ if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
+ e2_p->value = convert (TREE_TYPE (e2_p->value),
+ TREE_OPERAND (e2_p->value, 0));
+ if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+ || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
+ || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
+ || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
+ {
+ error_at (loc, "%<__builtin_complex%> operand "
+ "not of real binary floating-point type");
+ expr.value = error_mark_node;
+ break;
+ }
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
+ {
+ error_at (loc,
+ "%<__builtin_complex%> operands of different types");
+ expr.value = error_mark_node;
+ break;
+ }
+ if (!flag_isoc99)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C90 does not support complex types");
+ expr.value = build2 (COMPLEX_EXPR,
+ build_complex_type
+ (TYPE_MAIN_VARIANT
+ (TREE_TYPE (e1_p->value))),
+ e1_p->value, e2_p->value);
+ break;
+ }
+ case RID_BUILTIN_SHUFFLE:
+ {
+ VEC(c_expr_t,gc) *cexpr_list;
+
+ c_parser_consume_token (parser);
+ if (!c_parser_get_builtin_args (parser,
+ "__builtin_shuffle",
+ &cexpr_list))
+ {
+ expr.value = error_mark_node;
+ break;
+ }
+
+ if (VEC_length (c_expr_t, cexpr_list) == 2)
+ expr.value =
+ c_build_vec_perm_expr
+ (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+ NULL_TREE, VEC_index (c_expr_t, cexpr_list, 1)->value);
+
+ else if (VEC_length (c_expr_t, cexpr_list) == 3)
+ expr.value =
+ c_build_vec_perm_expr
+ (loc, VEC_index (c_expr_t, cexpr_list, 0)->value,
+ VEC_index (c_expr_t, cexpr_list, 1)->value,
+ VEC_index (c_expr_t, cexpr_list, 2)->value);
+ else
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_shuffle%>");
+ expr.value = error_mark_node;
+ }
+ break;
+ }
case RID_AT_SELECTOR:
gcc_assert (c_dialect_objc ());
c_parser_consume_token (parser);
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index cda5d06863a..b3e756cc076 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -130,6 +130,22 @@ struct c_expr
tree original_type;
};
+/* Type alias for struct c_expr. This allows to use the structure
+ inside the VEC types. */
+typedef struct c_expr c_expr_t;
+
+/* A varray of c_expr_t. */
+DEF_VEC_O (c_expr_t);
+DEF_VEC_ALLOC_O (c_expr_t, gc);
+DEF_VEC_ALLOC_O (c_expr_t, heap);
+
+/* Append a new c_expr_t element to V. */
+#define C_EXPR_APPEND(V, ELEM) \
+ do { \
+ c_expr_t *__elem_p = VEC_safe_push (c_expr_t, gc, V, NULL); \
+ *__elem_p = (ELEM); \
+ } while (0)
+
/* A kind of type specifier. Note that this information is currently
only used to distinguish tag definitions, tag references and typeof
uses. */
@@ -579,6 +595,7 @@ extern tree c_begin_omp_task (void);
extern tree c_finish_omp_task (location_t, tree, tree);
extern tree c_finish_omp_clauses (tree);
extern tree c_build_va_arg (location_t, tree, tree);
+extern tree c_build_vec_perm_expr (location_t, tree, tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index e1c17a2c211..7dfdae2b38e 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -2307,7 +2307,7 @@ build_array_ref (location_t loc, tree array, tree index)
if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
{
- error_at (loc,
+ error_at (loc,
"subscripted value is neither array nor pointer nor vector");
return error_mark_node;
@@ -2339,8 +2339,8 @@ build_array_ref (location_t loc, tree array, tree index)
index = default_conversion (index);
gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
-
- /* For vector[index], convert the vector to a
+
+ /* For vector[index], convert the vector to a
pointer of the underlying type. */
if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE)
{
@@ -2348,11 +2348,11 @@ build_array_ref (location_t loc, tree array, tree index)
tree type1;
if (TREE_CODE (index) == INTEGER_CST)
- if (!host_integerp (index, 1)
- || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
+ if (!host_integerp (index, 1)
+ || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
>= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array))))
warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
-
+
c_common_mark_addressable_vec (array);
type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
type = build_pointer_type (type);
@@ -2766,7 +2766,8 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
&& !comptypes (fntype, TREE_TYPE (tem)))
{
tree return_type = TREE_TYPE (fntype);
- tree trap = build_function_call (loc, built_in_decls[BUILT_IN_TRAP],
+ tree trap = build_function_call (loc,
+ builtin_decl_explicit (BUILT_IN_TRAP),
NULL_TREE);
int i;
@@ -2845,6 +2846,98 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
}
return require_complete_type (result);
}
+
+/* Build a VEC_PERM_EXPR if V0, V1 and MASK are not error_mark_nodes
+ and have vector types, V0 has the same type as V1, and the number of
+ elements of V0, V1, MASK is the same.
+
+ In case V1 is a NULL_TREE it is assumed that __builtin_shuffle was
+ called with two arguments. In this case implementation passes the
+ first argument twice in order to share the same tree code. This fact
+ could enable the mask-values being twice the vector length. This is
+ an implementation accident and this semantics is not guaranteed to
+ the user. */
+tree
+c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
+{
+ tree ret;
+ bool wrap = true;
+ bool maybe_const = false;
+ bool two_arguments = false;
+
+ if (v1 == NULL_TREE)
+ {
+ two_arguments = true;
+ v1 = v0;
+ }
+
+ if (v0 == error_mark_node || v1 == error_mark_node
+ || mask == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (TREE_TYPE (mask)) != VECTOR_TYPE
+ || TREE_CODE (TREE_TYPE (TREE_TYPE (mask))) != INTEGER_TYPE)
+ {
+ error_at (loc, "__builtin_shuffle last argument must "
+ "be an integer vector");
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (TREE_TYPE (v0)) != VECTOR_TYPE
+ || TREE_CODE (TREE_TYPE (v1)) != VECTOR_TYPE)
+ {
+ error_at (loc, "__builtin_shuffle arguments must be vectors");
+ return error_mark_node;
+ }
+
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1)))
+ {
+ error_at (loc, "__builtin_shuffle argument vectors must be of "
+ "the same type");
+ return error_mark_node;
+ }
+
+ if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0))
+ != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1))
+ != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))
+ {
+ error_at (loc, "__builtin_shuffle number of elements of the "
+ "argument vector(s) and the mask vector should "
+ "be the same");
+ return error_mark_node;
+ }
+
+ if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
+ != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
+ {
+ error_at (loc, "__builtin_shuffle argument vector(s) inner type "
+ "must have the same size as inner type of the mask");
+ return error_mark_node;
+ }
+
+ /* Avoid C_MAYBE_CONST_EXPRs inside VEC_PERM_EXPR. */
+ v0 = c_fully_fold (v0, false, &maybe_const);
+ wrap &= maybe_const;
+
+ if (two_arguments)
+ v1 = v0 = save_expr (v0);
+ else
+ {
+ v1 = c_fully_fold (v1, false, &maybe_const);
+ wrap &= maybe_const;
+ }
+
+ mask = c_fully_fold (mask, false, &maybe_const);
+ wrap &= maybe_const;
+
+ ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask);
+
+ if (!wrap)
+ ret = c_wrap_maybe_const (ret, true);
+
+ return ret;
+}
/* Convert the argument expressions in the vector VALUES
to the types in the list TYPELIST.
@@ -3167,7 +3260,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{
- error_at (input_location,
+ error_at (input_location,
"too few arguments to function %qE", function);
if (fundecl && !DECL_BUILT_IN (fundecl))
inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
@@ -3566,7 +3659,7 @@ build_unary_op (location_t location,
/* Complain about anything that is not a true lvalue. In
Objective-C, skip this check for property_refs. */
- if (!objc_is_property_ref (arg)
+ if (!objc_is_property_ref (arg)
&& !lvalue_or_else (location,
arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
@@ -3683,7 +3776,7 @@ build_unary_op (location_t location,
need to ask Objective-C to build the increment or decrement
expression for it. */
if (objc_is_property_ref (arg))
- return objc_build_incr_expr_for_property_ref (location, code,
+ return objc_build_incr_expr_for_property_ref (location, code,
arg, inc);
/* Report a read-only lvalue. */
@@ -5926,7 +6019,7 @@ void
pedwarn_init (location_t location, int opt, const char *gmsgid)
{
char *ofwhat;
-
+
/* The gmsgid may be a format string with %< and %>. */
pedwarn (location, opt, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
@@ -9344,8 +9437,8 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
tree type1 = TREE_TYPE (op1);
bool integer_only_op = false;
enum stv_conv ret = stv_firstarg;
-
- gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
+
+ gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
|| TREE_CODE (type1) == VECTOR_TYPE);
switch (code)
{
@@ -9370,7 +9463,7 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
case BIT_AND_EXPR:
integer_only_op = true;
/* ... fall through ... */
-
+
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
@@ -9387,7 +9480,7 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
}
if (TREE_CODE (type0) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
{
if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
{
@@ -9399,7 +9492,7 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
}
else if (!integer_only_op
/* Allow integer --> real conversion if safe. */
- && (TREE_CODE (type0) == REAL_TYPE
+ && (TREE_CODE (type0) == REAL_TYPE
|| TREE_CODE (type0) == INTEGER_TYPE)
&& SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
{
@@ -9414,7 +9507,7 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
default:
break;
}
-
+
return stv_nothing;
}
@@ -9529,8 +9622,8 @@ build_binary_op (location_t location, enum tree_code code,
int_const = int_const_or_overflow = false;
/* Do not apply default conversion in mixed vector/scalar expression. */
- if (convert_p
- && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE)
+ if (convert_p
+ && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE)
!= (TREE_CODE (TREE_TYPE (op1)) == VECTOR_TYPE)))
{
op0 = default_conversion (op0);
@@ -9608,7 +9701,7 @@ build_binary_op (location_t location, enum tree_code code,
if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
{
enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
-
+
switch (convert_flag)
{
case stv_error:
@@ -9974,7 +10067,7 @@ build_binary_op (location_t location, enum tree_code code,
{
if (code == EQ_EXPR)
warning_at (location,
- OPT_Waddress,
+ OPT_Waddress,
"the comparison will always evaluate as %<false%> "
"for the address of %qD will never be NULL",
TREE_OPERAND (op1, 0));
diff --git a/gcc/calls.c b/gcc/calls.c
index 3fa70b571f4..eeb6b2ec602 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -274,6 +274,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL)
{
tree t = fndecl;
+
/* Although a built-in FUNCTION_DECL and its non-__builtin
counterpart compare equal and get a shared mem_attrs, they
produce different dump output in compare-debug compilations,
@@ -281,10 +282,14 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
adds a different (but equivalent) entry, while the other
doesn't run the garbage collector at the same spot and then
shares the mem_attr with the equivalent entry. */
- if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
- && built_in_decls[DECL_FUNCTION_CODE (t)])
- t = built_in_decls[DECL_FUNCTION_CODE (t)];
- set_mem_expr (funmem, t);
+ if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL)
+ {
+ tree t2 = builtin_decl_explicit (DECL_FUNCTION_CODE (t));
+ if (t2)
+ t = t2;
+ }
+
+ set_mem_expr (funmem, t);
}
else if (fntree)
set_mem_expr (funmem, build_simple_mem_ref (CALL_EXPR_FN (fntree)));
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 20a409c4fae..b59cf7bc9f0 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -1488,6 +1488,16 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
edge e1, e2;
edge_iterator ei;
+ /* If we performed shrink-wrapping, edges to the EXIT_BLOCK_PTR can
+ only be distinguished for JUMP_INSNs. The two paths may differ in
+ whether they went through the prologue. Sibcalls are fine, we know
+ that we either didn't need or inserted an epilogue before them. */
+ if (crtl->shrink_wrapped
+ && single_succ_p (bb1) && single_succ (bb1) == EXIT_BLOCK_PTR
+ && !JUMP_P (BB_END (bb1))
+ && !(CALL_P (BB_END (bb1)) && SIBLING_CALL_P (BB_END (bb1))))
+ return false;
+
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
if (single_succ_p (bb1)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 1495633840b..6fb9ee0c5a1 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -530,7 +530,7 @@ update_alias_info_with_stack_vars (void)
/* Make the SSA name point to all partition members. */
pi = get_ptr_info (name);
- pt_solution_set (&pi->pt, part, false, false);
+ pt_solution_set (&pi->pt, part, false);
}
/* Make all points-to sets that contain one member of a partition
@@ -1858,7 +1858,8 @@ expand_call_stmt (gimple stmt)
CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
if (decl
&& DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
+ && (DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA
+ || DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA_WITH_ALIGN))
CALL_ALLOCA_FOR_VAR_P (exp) = gimple_call_alloca_for_var_p (stmt);
else
CALL_FROM_THUNK_P (exp) = gimple_call_from_thunk_p (stmt);
@@ -3264,6 +3265,9 @@ expand_debug_expr (tree exp)
case VEC_UNPACK_LO_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ case VEC_PERM_EXPR:
return NULL;
/* Misc codes. */
@@ -3318,6 +3322,7 @@ expand_debug_expr (tree exp)
return NULL;
case WIDEN_SUM_EXPR:
+ case WIDEN_LSHIFT_EXPR:
if (SCALAR_INT_MODE_P (GET_MODE (op0))
&& SCALAR_INT_MODE_P (mode))
{
@@ -3326,7 +3331,8 @@ expand_debug_expr (tree exp)
0)))
? ZERO_EXTEND : SIGN_EXTEND, mode, op0,
inner_mode);
- return simplify_gen_binary (PLUS, mode, op0, op1);
+ return simplify_gen_binary (TREE_CODE (exp) == WIDEN_LSHIFT_EXPR
+ ? ASHIFT : PLUS, mode, op0, op1);
}
return NULL;
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index b3f045bbbcb..f06dbc83b1d 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1273,7 +1273,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
gcc_unreachable ();
#endif
}
- JUMP_LABEL (BB_END (jump_block)) = jump_label;
+ set_return_jump_label (BB_END (jump_block));
}
else
{
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index c75c1300408..ef71b5bed7c 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1219,7 +1219,6 @@ handle_alias_pairs (void)
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
{
if (TREE_CODE (p->decl) == FUNCTION_DECL
- && !lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))
&& (target_node = cgraph_node_for_asm (p->target)) != NULL)
{
src_node = cgraph_get_node (p->decl);
@@ -1231,12 +1230,12 @@ handle_alias_pairs (void)
However for weakref we insist on EXTERNAL flag being set.
See gcc.dg/attr-alias-5.c */
if (DECL_EXTERNAL (p->decl))
- DECL_EXTERNAL (p->decl) = 0;
+ DECL_EXTERNAL (p->decl) = lookup_attribute ("weakref",
+ DECL_ATTRIBUTES (p->decl)) != NULL;
cgraph_create_function_alias (p->decl, target_node->decl);
VEC_unordered_remove (alias_pair, alias_pairs, i);
}
else if (TREE_CODE (p->decl) == VAR_DECL
- && !lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))
&& (target_vnode = varpool_node_for_asm (p->target)) != NULL)
{
/* Normally EXTERNAL flag is used to mark external inlines,
@@ -1245,7 +1244,8 @@ handle_alias_pairs (void)
However for weakref we insist on EXTERNAL flag being set.
See gcc.dg/attr-alias-5.c */
if (DECL_EXTERNAL (p->decl))
- DECL_EXTERNAL (p->decl) = 0;
+ DECL_EXTERNAL (p->decl) = lookup_attribute ("weakref",
+ DECL_ATTRIBUTES (p->decl)) != NULL;
varpool_create_variable_alias (p->decl, target_vnode->decl);
VEC_unordered_remove (alias_pair, alias_pairs, i);
}
@@ -1798,7 +1798,6 @@ cgraph_expand_function (struct cgraph_node *node)
announce_function (decl);
node->process = 0;
- assemble_thunks_and_aliases (node);
gcc_assert (node->lowered);
/* Generate RTL for the body of DECL. */
@@ -1808,6 +1807,14 @@ cgraph_expand_function (struct cgraph_node *node)
gcc_assert (TREE_ASM_WRITTEN (decl));
current_function_decl = NULL;
gcc_assert (!cgraph_preserve_function_body_p (node));
+
+ /* It would make a lot more sense to output thunks before function body to get more
+ forward and lest backwarding jumps. This is however would need solving problem
+ with comdats. See PR48668. Also aliases must come after function itself to
+ make one pass assemblers, like one on AIX happy. See PR 50689.
+ FIXME: Perhaps thunks should be move before function IFF they are not in comdat
+ groups. */
+ assemble_thunks_and_aliases (node);
cgraph_release_function_body (node);
/* Eliminate all call edges. This is important so the GIMPLE_CALL no longer
points to the dead function body. */
@@ -2057,6 +2064,26 @@ ipa_passes (void)
bitmap_obstack_release (NULL);
}
+/* Weakrefs may be associated to external decls and thus not output
+ at expansion time. Emit all neccesary aliases. */
+
+static void
+output_weakrefs (void)
+{
+ struct cgraph_node *node;
+ struct varpool_node *vnode;
+ for (node = cgraph_nodes; node; node = node->next)
+ if (node->alias && node->thunk.alias && DECL_EXTERNAL (node->decl)
+ && !TREE_ASM_WRITTEN (node->decl))
+ assemble_alias (node->decl,
+ DECL_ASSEMBLER_NAME (node->thunk.alias));
+ for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+ if (vnode->alias && vnode->alias_of && DECL_EXTERNAL (vnode->decl)
+ && !TREE_ASM_WRITTEN (vnode->decl))
+ assemble_alias (vnode->decl,
+ DECL_ASSEMBLER_NAME (vnode->alias_of));
+}
+
/* Perform simple optimizations based on callgraph. */
@@ -2143,6 +2170,8 @@ cgraph_optimize (void)
varpool_assemble_pending_decls ();
}
+
+ output_weakrefs ();
cgraph_process_new_functions ();
cgraph_state = CGRAPH_STATE_FINISHED;
diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
index bca078442f7..3cffd662f92 100644
--- a/gcc/combine-stack-adj.c
+++ b/gcc/combine-stack-adj.c
@@ -296,10 +296,11 @@ record_stack_refs (rtx *xp, void *data)
return 0;
}
-/* If INSN has a REG_ARGS_SIZE note, move it to LAST. */
+/* If INSN has a REG_ARGS_SIZE note, move it to LAST.
+ AFTER is true iff LAST follows INSN in the instruction stream. */
static void
-maybe_move_args_size_note (rtx last, rtx insn)
+maybe_move_args_size_note (rtx last, rtx insn, bool after)
{
rtx note, last_note;
@@ -309,7 +310,12 @@ maybe_move_args_size_note (rtx last, rtx insn)
last_note = find_reg_note (last, REG_ARGS_SIZE, NULL_RTX);
if (last_note)
- XEXP (last_note, 0) = XEXP (note, 0);
+ {
+ /* The ARGS_SIZE notes are *not* cumulative. They represent an
+ absolute value, and the "most recent" note wins. */
+ if (!after)
+ XEXP (last_note, 0) = XEXP (note, 0);
+ }
else
add_reg_note (last, REG_ARGS_SIZE, XEXP (note, 0));
}
@@ -385,7 +391,7 @@ combine_stack_adjustments_for_block (basic_block bb)
last_sp_adjust + this_adjust,
this_adjust))
{
- maybe_move_args_size_note (last_sp_set, insn);
+ maybe_move_args_size_note (last_sp_set, insn, false);
/* It worked! */
delete_insn (insn);
@@ -403,6 +409,8 @@ combine_stack_adjustments_for_block (basic_block bb)
last_sp_adjust + this_adjust,
-last_sp_adjust))
{
+ maybe_move_args_size_note (insn, last_sp_set, true);
+
/* It worked! */
delete_insn (last_sp_set);
last_sp_set = insn;
diff --git a/gcc/combine.c b/gcc/combine.c
index 6c3b17ca6ea..29411149173 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -13274,13 +13274,14 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
break;
case REG_ARGS_SIZE:
- {
- /* ??? How to distribute between i3-i1. Assume i3 contains the
- entire adjustment. Assert i3 contains at least some adjust. */
- int old_size, args_size = INTVAL (XEXP (note, 0));
- old_size = fixup_args_size_notes (PREV_INSN (i3), i3, args_size);
- gcc_assert (old_size != args_size);
- }
+ /* ??? How to distribute between i3-i1. Assume i3 contains the
+ entire adjustment. Assert i3 contains at least some adjust. */
+ if (!noop_move_p (i3))
+ {
+ int old_size, args_size = INTVAL (XEXP (note, 0));
+ old_size = fixup_args_size_notes (PREV_INSN (i3), i3, args_size);
+ gcc_assert (old_size != args_size);
+ }
break;
case REG_NORETURN:
diff --git a/gcc/common.opt b/gcc/common.opt
index a1e02dfba81..41c3a55f83f 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -736,6 +736,10 @@ Wcoverage-mismatch
Common Var(warn_coverage_mismatch) Init(1) Warning
Warn in case profiles in -fprofile-use do not match
+Wvector-operation-performance
+Common Var(warn_vector_operation_performance) Warning
+Warn when a vector operation is compiled outside the SIMD
+
Xassembler
Driver Separate
@@ -1814,6 +1818,11 @@ fshow-column
Common Report Var(flag_show_column) Init(1)
Show column numbers in diagnostics, when available. Default on
+fshrink-wrap
+Common Report Var(flag_shrink_wrap) Optimization
+Emit function prologues only before parts of the function that need it,
+rather than at the top of the function.
+
fsignaling-nans
Common Report Var(flag_signaling_nans) Optimization SetByCombined
Disable optimizations observable by IEEE signaling NaNs
diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c
index e5b2088292e..8d7fd010b9d 100644
--- a/gcc/compare-elim.c
+++ b/gcc/compare-elim.c
@@ -356,7 +356,7 @@ find_comparisons_in_bb (struct dom_walk_data *data ATTRIBUTE_UNUSED,
/* Look to see if the flags register is live outgoing here, and
incoming to any successor not part of the extended basic block. */
- if (bitmap_bit_p (&DF_LIVE_BB_INFO (bb)->out, targetm.flags_regnum))
+ if (bitmap_bit_p (df_get_live_out (bb), targetm.flags_regnum))
{
edge e;
edge_iterator ei;
@@ -364,7 +364,7 @@ find_comparisons_in_bb (struct dom_walk_data *data ATTRIBUTE_UNUSED,
FOR_EACH_EDGE (e, ei, bb->succs)
{
basic_block dest = e->dest;
- if (bitmap_bit_p (&DF_LIVE_BB_INFO (dest)->in,
+ if (bitmap_bit_p (df_get_live_in (bb),
targetm.flags_regnum)
&& !single_pred_p (dest))
{
@@ -580,8 +580,6 @@ try_eliminate_compare (struct comparison *cmp)
static unsigned int
execute_compare_elim_after_reload (void)
{
- df_set_flags (DF_DEFER_INSN_RESCAN);
- df_live_add_problem ();
df_analyze ();
gcc_checking_assert (all_compares == NULL);
@@ -602,8 +600,6 @@ execute_compare_elim_after_reload (void)
VEC_free (comparison_struct_p, heap, all_compares);
all_compares = NULL;
-
- df_analyze ();
}
return 0;
diff --git a/gcc/config.gcc b/gcc/config.gcc
index dec145bb397..76487f633f9 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -186,6 +186,13 @@
# configure_default_options
# Set to an initializer for configure_default_options
# in configargs.h, based on --with-cpu et cetera.
+#
+# native_system_header_dir
+# Where system header files are found for this
+# target. This defaults to /usr/include. If
+# the --with-sysroot configure option or the
+# --sysroot command line option is used this
+# will be relative to the sysroot.
# The following variables are used in each case-construct to build up the
# outgoing variables:
@@ -238,6 +245,7 @@ default_gnu_indirect_function=no
target_gtfiles=
need_64bit_hwint=
need_64bit_isa=
+native_system_header_dir=/usr/include
# Don't carry these over build->host->target. Please.
xm_file=
@@ -596,7 +604,8 @@ case ${target} in
*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-kopensolaris*-gnu)
:;;
*-*-gnu*)
- tmake_file="$tmake_file t-gnu";;
+ native_system_header_dir=/include
+ ;;
esac
# glibc / uclibc / bionic switch.
# uclibc and bionic aren't usable for GNU/Hurd and neither for GNU/k*BSD.
@@ -1235,11 +1244,11 @@ x86_64-*-darwin*)
;;
i[34567]86-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
- tmake_file="${tmake_file} i386/t-i386elf t-svr4"
+ tmake_file="${tmake_file} i386/t-i386elf i386/t-crtstuff t-svr4"
;;
x86_64-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h"
- tmake_file="${tmake_file} i386/t-i386elf t-svr4"
+ tmake_file="${tmake_file} i386/t-i386elf i386/t-crtstuff t-svr4"
;;
i[34567]86-*-freebsd*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h"
@@ -1382,7 +1391,7 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu)
i[34567]86-pc-msdosdjgpp*)
xm_file=i386/xm-djgpp.h
tm_file="dbxcoff.h ${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/djgpp.h i386/djgpp-stdint.h"
- tmake_file="${tmake_file} i386/t-djgpp"
+ native_system_header_dir=/dev/env/DJDIR/include
extra_options="${extra_options} i386/djgpp.opt"
gnu_ld=yes
gas=yes
@@ -1552,6 +1561,7 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
tmake_file="${tmake_file} i386/t-mingw32"
;;
esac
+ native_system_header_dir=/mingw/include
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
extra_options="${extra_options} i386/cygming.opt i386/mingw.opt"
case ${target} in
@@ -2575,6 +2585,7 @@ sparc64-*-openbsd*)
spu-*-elf*)
tm_file="dbxelf.h elfos.h spu/spu-elf.h spu/spu.h newlib-stdint.h"
tmake_file="spu/t-spu-elf"
+ native_system_header_dir=/include
extra_headers="spu_intrinsics.h spu_internals.h vmx2spu.h spu_mfcio.h vec_types.h spu_cache.h"
extra_modes=spu/spu-modes.def
c_target_objs="${c_target_objs} spu-c.o"
@@ -3314,7 +3325,7 @@ case "${target}" in
| k8 | k8-sse3 | athlon64 | athlon64-sse3 | opteron \
| opteron-sse3 | athlon-fx | bdver2 | bdver1 | btver1 \
| amdfam10 | barcelona | nocona | core2 | corei7 \
- | corei7-avx | atom)
+ | corei7-avx | core-avx-i | core-avx2 | atom)
# OK
;;
*)
diff --git a/gcc/config.host b/gcc/config.host
index df8ba8fa801..696c79e3507 100644
--- a/gcc/config.host
+++ b/gcc/config.host
@@ -100,6 +100,14 @@ case ${host} in
esac
case ${host} in
+ arm*-*-linux*)
+ case ${target} in
+ arm*-*-*)
+ host_extra_gcc_objs="driver-arm.o"
+ host_xmake_file="${host_xmake_file} arm/x-arm"
+ ;;
+ esac
+ ;;
alpha*-*-linux* | alpha*-dec-osf*)
case ${target} in
alpha*-*-linux* | alpha*-dec-osf*)
diff --git a/gcc/config.in b/gcc/config.in
index fd50da3b191..b041cba7dba 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -759,6 +759,13 @@
#endif
+/* Define to 1 if we found a declaration for 'madvise', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_MADVISE
+#endif
+
+
/* Define to 1 if we found a declaration for 'malloc', otherwise define to 0.
*/
#ifndef USED_FOR_TARGET
@@ -1282,6 +1289,12 @@
#endif
+/* Define to 1 if you have the `madvise' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MADVISE
+#endif
+
+
/* Define to 1 if you have the <malloc.h> header file. */
#ifndef USED_FOR_TARGET
#undef HAVE_MALLOC_H
diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
index f9ad1c9e13e..cd4cefbc330 100644
--- a/gcc/config/arm/arm-c.c
+++ b/gcc/config/arm/arm-c.c
@@ -1,20 +1,20 @@
-/* Copyright (C) 2007, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
@@ -25,21 +25,21 @@ along with GCC; see the file COPYING3. If not see
#include "output.h"
#include "c-family/c-common.h"
-
/* Output C specific EABI object attributes. These can not be done in
arm.c because they require information from the C frontend. */
-static void arm_output_c_attributes(void)
+static void
+arm_output_c_attributes (void)
{
- /* Tag_ABI_PCS_wchar_t. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 18, %d\n",
- (int)(TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT));
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_PCS_wchar_t, 18,
+ (int)(TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT));
}
/* Setup so that common code calls arm_output_c_attributes. */
-void arm_lang_object_attributes_init(void)
+void
+arm_lang_object_attributes_init (void)
{
arm_lang_output_object_attributes_hook = arm_output_c_attributes;
}
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 51614396da4..f1ada6f9a73 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1062,12 +1062,12 @@ arm_set_fixed_optab_libfunc (optab optable, enum machine_mode mode,
int num_suffix)
{
char buffer[50];
-
+
if (num_suffix == 0)
sprintf (buffer, "__gnu_%s%s", funcname, modename);
else
sprintf (buffer, "__gnu_%s%s%d", funcname, modename, num_suffix);
-
+
set_optab_libfunc (optable, mode, buffer);
}
@@ -1078,13 +1078,13 @@ arm_set_fixed_conv_libfunc (convert_optab optable, enum machine_mode to,
{
char buffer[50];
const char *maybe_suffix_2 = "";
-
+
/* Follow the logic for selecting a "2" suffix in fixed-bit.h. */
if (ALL_FIXED_POINT_MODE_P (from) && ALL_FIXED_POINT_MODE_P (to)
&& UNSIGNED_FIXED_POINT_MODE_P (from) == UNSIGNED_FIXED_POINT_MODE_P (to)
&& ALL_FRACT_MODE_P (from) == ALL_FRACT_MODE_P (to))
maybe_suffix_2 = "2";
-
+
sprintf (buffer, "__gnu_%s%s%s%s", funcname, fromname, toname,
maybe_suffix_2);
@@ -1210,11 +1210,11 @@ arm_init_libfuncs (void)
(arm_fp16_format == ARM_FP16_FORMAT_IEEE
? "__gnu_f2h_ieee"
: "__gnu_f2h_alternative"));
- set_conv_libfunc (sext_optab, SFmode, HFmode,
+ set_conv_libfunc (sext_optab, SFmode, HFmode,
(arm_fp16_format == ARM_FP16_FORMAT_IEEE
? "__gnu_h2f_ieee"
: "__gnu_h2f_alternative"));
-
+
/* Arithmetic. */
set_optab_libfunc (add_optab, HFmode, NULL);
set_optab_libfunc (sdiv_optab, HFmode, NULL);
@@ -1380,14 +1380,14 @@ arm_build_builtin_va_list (void)
{
tree va_list_name;
tree ap_field;
-
+
if (!TARGET_AAPCS_BASED)
return std_build_builtin_va_list ();
/* AAPCS \S 7.1.4 requires that va_list be a typedef for a type
defined as:
- struct __va_list
+ struct __va_list
{
void *__ap;
};
@@ -1411,7 +1411,7 @@ arm_build_builtin_va_list (void)
TYPE_STUB_DECL (va_list_type) = va_list_name;
/* Create the __ap field. */
ap_field = build_decl (BUILTINS_LOCATION,
- FIELD_DECL,
+ FIELD_DECL,
get_identifier ("__ap"),
ptr_type_node);
DECL_ARTIFICIAL (ap_field) = 1;
@@ -1437,7 +1437,7 @@ arm_extract_valist_ptr (tree valist)
if (TARGET_AAPCS_BASED)
{
tree ap_field = TYPE_FIELDS (TREE_TYPE (valist));
- valist = build3 (COMPONENT_REF, TREE_TYPE (ap_field),
+ valist = build3 (COMPONENT_REF, TREE_TYPE (ap_field),
valist, ap_field, NULL_TREE);
}
@@ -1454,7 +1454,7 @@ arm_expand_builtin_va_start (tree valist, rtx nextarg)
/* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. */
static tree
-arm_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+arm_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
gimple_seq *post_p)
{
valist = arm_extract_valist_ptr (valist);
@@ -2312,7 +2312,7 @@ use_return_insn (int iscond, rtx sibling)
if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM))
return 0;
- if (flag_pic
+ if (flag_pic
&& arm_pic_register != INVALID_REGNUM
&& df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
return 0;
@@ -2368,7 +2368,7 @@ const_ok_for_arm (HOST_WIDE_INT i)
/* Get the number of trailing zeros. */
lowbit = ffs((int) i) - 1;
-
+
/* Only even shifts are allowed in ARM mode so round down to the
nearest even number. */
if (TARGET_ARM)
@@ -2632,10 +2632,10 @@ optimal_immediate_sequence_1 (enum rtx_code code, unsigned HOST_WIDE_INT val,
/* Try and find a way of doing the job in either two or three
instructions.
-
+
In ARM mode we can use 8-bit constants, rotated to any 2-bit aligned
location. We start at position I. This may be the MSB, or
- optimial_immediate_sequence may have positioned it at the largest block
+ optimial_immediate_sequence may have positioned it at the largest block
of zeros that are aligned on a 2-bit boundary. We then fill up the temps,
wrapping around to the top of the word when we drop off the bottom.
In the worst case this code should produce no more than four insns.
@@ -2684,11 +2684,11 @@ optimal_immediate_sequence_1 (enum rtx_code code, unsigned HOST_WIDE_INT val,
/* Next, see if we can do a better job with a thumb2 replicated
constant.
-
+
We do it this way around to catch the cases like 0x01F001E0 where
two 8-bit immediates would work, but a replicated constant would
make it worse.
-
+
TODO: 16-bit constants that don't clear all the bits, but still win.
TODO: Arithmetic splitting for set/add/sub, rather than bitwise. */
if (TARGET_THUMB2)
@@ -2716,7 +2716,7 @@ optimal_immediate_sequence_1 (enum rtx_code code, unsigned HOST_WIDE_INT val,
|| (matching_bytes == 2
&& const_ok_for_op (remainder & ~tmp2, code))))
{
- /* At least 3 of the bytes match, and the fourth has at
+ /* At least 3 of the bytes match, and the fourth has at
least as many bits set, or two of the bytes match
and it will only require one more insn to finish. */
result = tmp2;
@@ -3629,7 +3629,7 @@ arm_libcall_uses_aapcs_base (const_rtx libcall)
convert_optab_libfunc (sfloat_optab, SFmode, DImode));
add_libcall (libcall_htab,
convert_optab_libfunc (sfloat_optab, DFmode, DImode));
-
+
add_libcall (libcall_htab,
convert_optab_libfunc (ufloat_optab, SFmode, SImode));
add_libcall (libcall_htab,
@@ -3949,7 +3949,7 @@ arm_get_pcs_model (const_tree type, const_tree decl)
(no argument is ever a candidate for a co-processor
register). */
bool base_rules = stdarg_p (type);
-
+
if (user_convention)
{
if (user_pcs > ARM_PCS_AAPCS_LOCAL)
@@ -3984,7 +3984,7 @@ arm_get_pcs_model (const_tree type, const_tree decl)
static void
aapcs_vfp_cum_init (CUMULATIVE_ARGS *pcum ATTRIBUTE_UNUSED,
const_tree fntype ATTRIBUTE_UNUSED,
- rtx libcall ATTRIBUTE_UNUSED,
+ rtx libcall ATTRIBUTE_UNUSED,
const_tree fndecl ATTRIBUTE_UNUSED)
{
/* Record the unallocated VFP registers. */
@@ -4089,7 +4089,7 @@ aapcs_vfp_sub_candidate (const_tree type, enum machine_mode *modep)
return count;
}
-
+
case RECORD_TYPE:
{
int count = 0;
@@ -4237,7 +4237,7 @@ aapcs_vfp_is_return_candidate (enum arm_pcs pcs_variant,
}
static bool
-aapcs_vfp_is_call_candidate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+aapcs_vfp_is_call_candidate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
const_tree type)
{
if (!use_vfp_abi (pcum->pcs_variant, false))
@@ -4255,7 +4255,7 @@ aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
int shift = GET_MODE_SIZE (pcum->aapcs_vfp_rmode) / GET_MODE_SIZE (SFmode);
unsigned mask = (1 << (shift * pcum->aapcs_vfp_rcount)) - 1;
int regno;
-
+
for (regno = 0; regno < NUM_VFP_ARG_REGS; regno += shift)
if (((pcum->aapcs_vfp_regs_free >> regno) & mask) == mask)
{
@@ -4282,10 +4282,10 @@ aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
par = gen_rtx_PARALLEL (mode, rtvec_alloc (rcount));
for (i = 0; i < rcount; i++)
{
- rtx tmp = gen_rtx_REG (rmode,
+ rtx tmp = gen_rtx_REG (rmode,
FIRST_VFP_REGNUM + regno + i * rshift);
tmp = gen_rtx_EXPR_LIST
- (VOIDmode, tmp,
+ (VOIDmode, tmp,
GEN_INT (i * GET_MODE_SIZE (rmode)));
XVECEXP (par, 0, i) = tmp;
}
@@ -4314,7 +4314,7 @@ aapcs_vfp_allocate_return_reg (enum arm_pcs pcs_variant ATTRIBUTE_UNUSED,
int i;
rtx par;
int shift;
-
+
aapcs_vfp_is_call_or_return_candidate (pcs_variant, mode, type,
&ag_mode, &count);
@@ -4333,7 +4333,7 @@ aapcs_vfp_allocate_return_reg (enum arm_pcs pcs_variant ATTRIBUTE_UNUSED,
for (i = 0; i < count; i++)
{
rtx tmp = gen_rtx_REG (ag_mode, FIRST_VFP_REGNUM + i * shift);
- tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp,
+ tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp,
GEN_INT (i * GET_MODE_SIZE (ag_mode)));
XVECEXP (par, 0, i) = tmp;
}
@@ -4370,7 +4370,7 @@ aapcs_vfp_advance (CUMULATIVE_ARGS *pcum ATTRIBUTE_UNUSED,
and stops after the first match. If that entry then fails to put
the argument into a co-processor register, the argument will go on
the stack. */
-static struct
+static struct
{
/* Initialize co-processor related state in CUMULATIVE_ARGS structure. */
void (*cum_init) (CUMULATIVE_ARGS *, const_tree, rtx, const_tree);
@@ -4406,7 +4406,7 @@ static struct
#undef AAPCS_CP
static int
-aapcs_select_call_coproc (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+aapcs_select_call_coproc (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
const_tree type)
{
int i;
@@ -4446,7 +4446,7 @@ aapcs_select_return_coproc (const_tree type, const_tree fntype)
int i;
for (i = 0; i < ARM_NUM_COPROC_SLOTS; i++)
- if (aapcs_cp_arg_layout[i].is_return_candidate (pcs_variant,
+ if (aapcs_cp_arg_layout[i].is_return_candidate (pcs_variant,
TYPE_MODE (type),
type))
return i;
@@ -4538,7 +4538,7 @@ aapcs_layout_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
anonymous argument which is on the stack. */
if (!named)
return;
-
+
/* Is this a potential co-processor register candidate? */
if (pcum->pcs_variant != ARM_PCS_AAPCS)
{
@@ -4638,7 +4638,7 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
{
if (arm_libcall_uses_aapcs_base (libname))
pcum->pcs_variant = ARM_PCS_AAPCS;
-
+
pcum->aapcs_ncrn = pcum->aapcs_next_ncrn = 0;
pcum->aapcs_reg = NULL_RTX;
pcum->aapcs_partial = 0;
@@ -5685,7 +5685,7 @@ thumb2_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
{
bool use_ldrd;
enum rtx_code code = GET_CODE (x);
-
+
if (arm_address_register_rtx_p (x, strict_p))
return 1;
@@ -5713,7 +5713,7 @@ thumb2_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
offset = INTVAL(addend);
if (GET_MODE_SIZE (mode) <= 4)
return (offset > -256 && offset < 256);
-
+
return (use_ldrd && offset > -1024 && offset < 1024
&& (offset & 3) == 0);
}
@@ -5869,14 +5869,14 @@ static bool
thumb2_index_mul_operand (rtx op)
{
HOST_WIDE_INT val;
-
+
if (GET_CODE(op) != CONST_INT)
return false;
val = INTVAL(op);
return (val == 1 || val == 2 || val == 4 || val == 8);
}
-
+
/* Return nonzero if INDEX is a valid Thumb-2 address index operand. */
static int
thumb2_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p)
@@ -6224,11 +6224,11 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno));
else
emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
-
+
*valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX,
LCT_PURE, /* LCT_CONST? */
Pmode, 1, reg, Pmode);
-
+
insns = get_insns ();
end_sequence ();
@@ -6246,7 +6246,7 @@ arm_tls_descseq_addr (rtx x, rtx reg)
GEN_INT (!TARGET_ARM)),
UNSPEC_TLS);
rtx reg0 = load_tls_operand (sum, gen_rtx_REG (SImode, 0));
-
+
emit_insn (gen_tlscall (x, labelno));
if (!reg)
reg = gen_reg_rtx (SImode);
@@ -6272,7 +6272,7 @@ legitimize_tls_address (rtx x, rtx reg)
reg = arm_tls_descseq_addr (x, reg);
tp = arm_load_tp (NULL_RTX);
-
+
dest = gen_rtx_PLUS (Pmode, tp, reg);
}
else
@@ -6290,20 +6290,20 @@ legitimize_tls_address (rtx x, rtx reg)
reg = arm_tls_descseq_addr (x, reg);
tp = arm_load_tp (NULL_RTX);
-
+
dest = gen_rtx_PLUS (Pmode, tp, reg);
}
else
{
insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32);
-
+
/* 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, const1_rtx),
UNSPEC_TLS);
dest = gen_reg_rtx (Pmode);
emit_libcall_block (insns, dest, ret, eqv);
-
+
/* Load the addend. */
addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x,
GEN_INT (TLS_LDO32)),
@@ -6550,9 +6550,26 @@ arm_legitimize_reload_address (rtx *p,
int opnum, int type,
int ind_levels ATTRIBUTE_UNUSED)
{
+ /* We must recognize output that we have already generated ourselves. */
+ if (GET_CODE (*p) == PLUS
+ && GET_CODE (XEXP (*p, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (*p, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (*p, 0), 1)) == CONST_INT
+ && GET_CODE (XEXP (*p, 1)) == CONST_INT)
+ {
+ push_reload (XEXP (*p, 0), NULL_RTX, &XEXP (*p, 0), NULL,
+ MODE_BASE_REG_CLASS (mode), GET_MODE (*p),
+ VOIDmode, 0, 0, opnum, (enum reload_type) type);
+ return true;
+ }
+
if (GET_CODE (*p) == PLUS
&& GET_CODE (XEXP (*p, 0)) == REG
&& ARM_REGNO_OK_FOR_BASE_P (REGNO (XEXP (*p, 0)))
+ /* If the base register is equivalent to a constant, let the generic
+ code handle it. Otherwise we will run into problems if a future
+ reload pass decides to rematerialize the constant. */
+ && !reg_equiv_constant (ORIGINAL_REGNO (XEXP (*p, 0)))
&& GET_CODE (XEXP (*p, 1)) == CONST_INT)
{
HOST_WIDE_INT val = INTVAL (XEXP (*p, 1));
@@ -7411,7 +7428,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
*total += rtx_cost (XEXP (XEXP (x, 0), 0), subcode, 0, speed);
return true;
}
-
+
return false;
case UMIN:
@@ -8321,9 +8338,9 @@ cortex_a9_sched_adjust_cost (rtx insn, rtx link, rtx dep, int * cost)
{
if (GET_CODE (PATTERN (insn)) == SET)
{
- if (GET_MODE_CLASS
+ if (GET_MODE_CLASS
(GET_MODE (SET_DEST (PATTERN (insn)))) == MODE_FLOAT
- || GET_MODE_CLASS
+ || GET_MODE_CLASS
(GET_MODE (SET_SRC (PATTERN (insn)))) == MODE_FLOAT)
{
enum attr_type attr_type_insn = get_attr_type (insn);
@@ -8343,7 +8360,7 @@ cortex_a9_sched_adjust_cost (rtx insn, rtx link, rtx dep, int * cost)
{
/* FMACS is a special case where the dependant
instruction can be issued 3 cycles before
- the normal latency in case of an output
+ the normal latency in case of an output
dependency. */
if ((attr_type_insn == TYPE_FMACS
|| attr_type_insn == TYPE_FMACD)
@@ -8411,8 +8428,8 @@ fa726te_sched_adjust_cost (rtx insn, rtx link, rtx dep, int * cost)
It corrects the value of COST based on the relationship between
INSN and DEP through the dependence LINK. It returns the new
value. There is a per-core adjust_cost hook to adjust scheduler costs
- and the per-core hook can choose to completely override the generic
- adjust_cost function. Only put bits of code into arm_adjust_cost that
+ and the per-core hook can choose to completely override the generic
+ adjust_cost function. Only put bits of code into arm_adjust_cost that
are common across all cores. */
static int
arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
@@ -8456,7 +8473,7 @@ arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
constant pool are cached, and that others will miss. This is a
hack. */
- if ((GET_CODE (src_mem) == SYMBOL_REF
+ if ((GET_CODE (src_mem) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (src_mem))
|| reg_mentioned_p (stack_pointer_rtx, src_mem)
|| reg_mentioned_p (frame_pointer_rtx, src_mem)
@@ -9851,7 +9868,7 @@ arm_cannot_copy_insn_p (rtx insn)
word. */
if (recog_memoized (insn) == CODE_FOR_tlscall)
return true;
-
+
return for_each_rtx (&PATTERN (insn), arm_note_pic_base, NULL);
}
@@ -10749,6 +10766,335 @@ gen_const_stm_seq (rtx *operands, int nops)
return true;
}
+/* Copy a block of memory using plain ldr/str/ldrh/strh instructions, to permit
+ unaligned copies on processors which support unaligned semantics for those
+ instructions. INTERLEAVE_FACTOR can be used to attempt to hide load latency
+ (using more registers) by doing e.g. load/load/store/store for a factor of 2.
+ An interleave factor of 1 (the minimum) will perform no interleaving.
+ Load/store multiple are used for aligned addresses where possible. */
+
+static void
+arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase,
+ HOST_WIDE_INT length,
+ unsigned int interleave_factor)
+{
+ rtx *regs = XALLOCAVEC (rtx, interleave_factor);
+ int *regnos = XALLOCAVEC (int, interleave_factor);
+ HOST_WIDE_INT block_size_bytes = interleave_factor * UNITS_PER_WORD;
+ HOST_WIDE_INT i, j;
+ HOST_WIDE_INT remaining = length, words;
+ rtx halfword_tmp = NULL, byte_tmp = NULL;
+ rtx dst, src;
+ bool src_aligned = MEM_ALIGN (srcbase) >= BITS_PER_WORD;
+ bool dst_aligned = MEM_ALIGN (dstbase) >= BITS_PER_WORD;
+ HOST_WIDE_INT srcoffset, dstoffset;
+ HOST_WIDE_INT src_autoinc, dst_autoinc;
+ rtx mem, addr;
+
+ gcc_assert (1 <= interleave_factor && interleave_factor <= 4);
+
+ /* Use hard registers if we have aligned source or destination so we can use
+ load/store multiple with contiguous registers. */
+ if (dst_aligned || src_aligned)
+ for (i = 0; i < interleave_factor; i++)
+ regs[i] = gen_rtx_REG (SImode, i);
+ else
+ for (i = 0; i < interleave_factor; i++)
+ regs[i] = gen_reg_rtx (SImode);
+
+ dst = copy_addr_to_reg (XEXP (dstbase, 0));
+ src = copy_addr_to_reg (XEXP (srcbase, 0));
+
+ srcoffset = dstoffset = 0;
+
+ /* Calls to arm_gen_load_multiple and arm_gen_store_multiple update SRC/DST.
+ For copying the last bytes we want to subtract this offset again. */
+ src_autoinc = dst_autoinc = 0;
+
+ for (i = 0; i < interleave_factor; i++)
+ regnos[i] = i;
+
+ /* Copy BLOCK_SIZE_BYTES chunks. */
+
+ for (i = 0; i + block_size_bytes <= length; i += block_size_bytes)
+ {
+ /* Load words. */
+ if (src_aligned && interleave_factor > 1)
+ {
+ emit_insn (arm_gen_load_multiple (regnos, interleave_factor, src,
+ TRUE, srcbase, &srcoffset));
+ src_autoinc += UNITS_PER_WORD * interleave_factor;
+ }
+ else
+ {
+ for (j = 0; j < interleave_factor; j++)
+ {
+ addr = plus_constant (src, srcoffset + j * UNITS_PER_WORD
+ - src_autoinc);
+ mem = adjust_automodify_address (srcbase, SImode, addr,
+ srcoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_loadsi (regs[j], mem));
+ }
+ srcoffset += block_size_bytes;
+ }
+
+ /* Store words. */
+ if (dst_aligned && interleave_factor > 1)
+ {
+ emit_insn (arm_gen_store_multiple (regnos, interleave_factor, dst,
+ TRUE, dstbase, &dstoffset));
+ dst_autoinc += UNITS_PER_WORD * interleave_factor;
+ }
+ else
+ {
+ for (j = 0; j < interleave_factor; j++)
+ {
+ addr = plus_constant (dst, dstoffset + j * UNITS_PER_WORD
+ - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, SImode, addr,
+ dstoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_storesi (mem, regs[j]));
+ }
+ dstoffset += block_size_bytes;
+ }
+
+ remaining -= block_size_bytes;
+ }
+
+ /* Copy any whole words left (note these aren't interleaved with any
+ subsequent halfword/byte load/stores in the interests of simplicity). */
+
+ words = remaining / UNITS_PER_WORD;
+
+ gcc_assert (words < interleave_factor);
+
+ if (src_aligned && words > 1)
+ {
+ emit_insn (arm_gen_load_multiple (regnos, words, src, TRUE, srcbase,
+ &srcoffset));
+ src_autoinc += UNITS_PER_WORD * words;
+ }
+ else
+ {
+ for (j = 0; j < words; j++)
+ {
+ addr = plus_constant (src,
+ srcoffset + j * UNITS_PER_WORD - src_autoinc);
+ mem = adjust_automodify_address (srcbase, SImode, addr,
+ srcoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_loadsi (regs[j], mem));
+ }
+ srcoffset += words * UNITS_PER_WORD;
+ }
+
+ if (dst_aligned && words > 1)
+ {
+ emit_insn (arm_gen_store_multiple (regnos, words, dst, TRUE, dstbase,
+ &dstoffset));
+ dst_autoinc += words * UNITS_PER_WORD;
+ }
+ else
+ {
+ for (j = 0; j < words; j++)
+ {
+ addr = plus_constant (dst,
+ dstoffset + j * UNITS_PER_WORD - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, SImode, addr,
+ dstoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_storesi (mem, regs[j]));
+ }
+ dstoffset += words * UNITS_PER_WORD;
+ }
+
+ remaining -= words * UNITS_PER_WORD;
+
+ gcc_assert (remaining < 4);
+
+ /* Copy a halfword if necessary. */
+
+ if (remaining >= 2)
+ {
+ halfword_tmp = gen_reg_rtx (SImode);
+
+ addr = plus_constant (src, srcoffset - src_autoinc);
+ mem = adjust_automodify_address (srcbase, HImode, addr, srcoffset);
+ emit_insn (gen_unaligned_loadhiu (halfword_tmp, mem));
+
+ /* Either write out immediately, or delay until we've loaded the last
+ byte, depending on interleave factor. */
+ if (interleave_factor == 1)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, HImode, addr, dstoffset);
+ emit_insn (gen_unaligned_storehi (mem,
+ gen_lowpart (HImode, halfword_tmp)));
+ halfword_tmp = NULL;
+ dstoffset += 2;
+ }
+
+ remaining -= 2;
+ srcoffset += 2;
+ }
+
+ gcc_assert (remaining < 2);
+
+ /* Copy last byte. */
+
+ if ((remaining & 1) != 0)
+ {
+ byte_tmp = gen_reg_rtx (SImode);
+
+ addr = plus_constant (src, srcoffset - src_autoinc);
+ mem = adjust_automodify_address (srcbase, QImode, addr, srcoffset);
+ emit_move_insn (gen_lowpart (QImode, byte_tmp), mem);
+
+ if (interleave_factor == 1)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, QImode, addr, dstoffset);
+ emit_move_insn (mem, gen_lowpart (QImode, byte_tmp));
+ byte_tmp = NULL;
+ dstoffset++;
+ }
+
+ remaining--;
+ srcoffset++;
+ }
+
+ /* Store last halfword if we haven't done so already. */
+
+ if (halfword_tmp)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, HImode, addr, dstoffset);
+ emit_insn (gen_unaligned_storehi (mem,
+ gen_lowpart (HImode, halfword_tmp)));
+ dstoffset += 2;
+ }
+
+ /* Likewise for last byte. */
+
+ if (byte_tmp)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, QImode, addr, dstoffset);
+ emit_move_insn (mem, gen_lowpart (QImode, byte_tmp));
+ dstoffset++;
+ }
+
+ gcc_assert (remaining == 0 && srcoffset == dstoffset);
+}
+
+/* From mips_adjust_block_mem:
+
+ Helper function for doing a loop-based block operation on memory
+ reference MEM. Each iteration of the loop will operate on LENGTH
+ bytes of MEM.
+
+ Create a new base register for use within the loop and point it to
+ the start of MEM. Create a new memory reference that uses this
+ register. Store them in *LOOP_REG and *LOOP_MEM respectively. */
+
+static void
+arm_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg,
+ rtx *loop_mem)
+{
+ *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
+
+ /* Although the new mem does not refer to a known location,
+ it does keep up to LENGTH bytes of alignment. */
+ *loop_mem = change_address (mem, BLKmode, *loop_reg);
+ set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
+}
+
+/* From mips_block_move_loop:
+
+ Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER
+ bytes at a time. LENGTH must be at least BYTES_PER_ITER. Assume that
+ the memory regions do not overlap. */
+
+static void
+arm_block_move_unaligned_loop (rtx dest, rtx src, HOST_WIDE_INT length,
+ unsigned int interleave_factor,
+ HOST_WIDE_INT bytes_per_iter)
+{
+ rtx label, src_reg, dest_reg, final_src, test;
+ HOST_WIDE_INT leftover;
+
+ leftover = length % bytes_per_iter;
+ length -= leftover;
+
+ /* Create registers and memory references for use within the loop. */
+ arm_adjust_block_mem (src, bytes_per_iter, &src_reg, &src);
+ arm_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest);
+
+ /* Calculate the value that SRC_REG should have after the last iteration of
+ the loop. */
+ final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
+ 0, 0, OPTAB_WIDEN);
+
+ /* Emit the start of the loop. */
+ label = gen_label_rtx ();
+ emit_label (label);
+
+ /* Emit the loop body. */
+ arm_block_move_unaligned_straight (dest, src, bytes_per_iter,
+ interleave_factor);
+
+ /* Move on to the next block. */
+ emit_move_insn (src_reg, plus_constant (src_reg, bytes_per_iter));
+ emit_move_insn (dest_reg, plus_constant (dest_reg, bytes_per_iter));
+
+ /* Emit the loop condition. */
+ test = gen_rtx_NE (VOIDmode, src_reg, final_src);
+ emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
+
+ /* Mop up any left-over bytes. */
+ if (leftover)
+ arm_block_move_unaligned_straight (dest, src, leftover, interleave_factor);
+}
+
+/* Emit a block move when either the source or destination is unaligned (not
+ aligned to a four-byte boundary). This may need further tuning depending on
+ core type, optimize_size setting, etc. */
+
+static int
+arm_movmemqi_unaligned (rtx *operands)
+{
+ HOST_WIDE_INT length = INTVAL (operands[2]);
+
+ if (optimize_size)
+ {
+ bool src_aligned = MEM_ALIGN (operands[1]) >= BITS_PER_WORD;
+ bool dst_aligned = MEM_ALIGN (operands[0]) >= BITS_PER_WORD;
+ /* Inlined memcpy using ldr/str/ldrh/strh can be quite big: try to limit
+ size of code if optimizing for size. We'll use ldm/stm if src_aligned
+ or dst_aligned though: allow more interleaving in those cases since the
+ resulting code can be smaller. */
+ unsigned int interleave_factor = (src_aligned || dst_aligned) ? 2 : 1;
+ HOST_WIDE_INT bytes_per_iter = (src_aligned || dst_aligned) ? 8 : 4;
+
+ if (length > 12)
+ arm_block_move_unaligned_loop (operands[0], operands[1], length,
+ interleave_factor, bytes_per_iter);
+ else
+ arm_block_move_unaligned_straight (operands[0], operands[1], length,
+ interleave_factor);
+ }
+ else
+ {
+ /* Note that the loop created by arm_block_move_unaligned_loop may be
+ subject to loop unrolling, which makes tuning this condition a little
+ redundant. */
+ if (length > 32)
+ arm_block_move_unaligned_loop (operands[0], operands[1], length, 4, 16);
+ else
+ arm_block_move_unaligned_straight (operands[0], operands[1], length, 4);
+ }
+
+ return 1;
+}
+
int
arm_gen_movmemqi (rtx *operands)
{
@@ -10761,8 +11107,13 @@ arm_gen_movmemqi (rtx *operands)
if (GET_CODE (operands[2]) != CONST_INT
|| GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[2]) > 64
- || INTVAL (operands[3]) & 3)
+ || INTVAL (operands[2]) > 64)
+ return 0;
+
+ if (unaligned_access && (INTVAL (operands[3]) & 3) != 0)
+ return arm_movmemqi_unaligned (operands);
+
+ if (INTVAL (operands[3]) & 3)
return 0;
dstbase = operands[0];
@@ -11080,7 +11431,7 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
/* A compare with a shifted operand. Because of canonicalization, the
comparison will have to be swapped when we emit the assembler. */
- if (GET_MODE (y) == SImode
+ if (GET_MODE (y) == SImode
&& (REG_P (y) || (GET_CODE (y) == SUBREG))
&& (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
|| GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ROTATE
@@ -11089,7 +11440,7 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
/* This operation is performed swapped, but since we only rely on the Z
flag we don't need an additional mode. */
- if (GET_MODE (y) == SImode
+ if (GET_MODE (y) == SImode
&& (REG_P (y) || (GET_CODE (y) == SUBREG))
&& GET_CODE (x) == NEG
&& (op == EQ || op == NE))
@@ -12439,7 +12790,7 @@ create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
still put the pool after the table. */
new_cost = arm_barrier_cost (from);
- if (count < max_count
+ if (count < max_count
&& (!selected || new_cost <= selected_cost))
{
selected = tmp;
@@ -12821,7 +13172,7 @@ arm_reorg (void)
if (TARGET_THUMB2)
thumb2_reorg ();
-
+
minipool_fix_head = minipool_fix_tail = NULL;
/* The first insn must always be a note, or the code below won't
@@ -13435,7 +13786,7 @@ output_move_double (rtx *operands, bool emit, int *count)
if (count)
*count = 1;
- /* The only case when this might happen is when
+ /* The only case when this might happen is when
you are looking at the length of a DImode instruction
that has an invalid constant in it. */
if (code0 == REG && code1 != MEM)
@@ -13444,7 +13795,6 @@ output_move_double (rtx *operands, bool emit, int *count)
*count = 2;
return "";
}
-
if (code0 == REG)
{
@@ -13472,7 +13822,6 @@ output_move_double (rtx *operands, bool emit, int *count)
gcc_assert (TARGET_LDRD);
if (emit)
output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands);
-
break;
case PRE_DEC:
@@ -13486,7 +13835,6 @@ output_move_double (rtx *operands, bool emit, int *count)
break;
case POST_INC:
-
if (emit)
{
if (TARGET_LDRD)
@@ -13675,7 +14023,7 @@ output_move_double (rtx *operands, bool emit, int *count)
}
if (GET_CODE (otherops[2]) == CONST_INT)
- {
+ {
if (emit)
{
if (!(const_ok_for_arm (INTVAL (otherops[2]))))
@@ -13683,7 +14031,6 @@ output_move_double (rtx *operands, bool emit, int *count)
else
output_asm_insn ("add%?\t%0, %1, %2", otherops);
}
-
}
else
{
@@ -13699,8 +14046,8 @@ output_move_double (rtx *operands, bool emit, int *count)
if (TARGET_LDRD)
return "ldr%(d%)\t%0, [%1]";
-
- return "ldm%(ia%)\t%1, %M0";
+
+ return "ldm%(ia%)\t%1, %M0";
}
else
{
@@ -13877,7 +14224,6 @@ output_move_double (rtx *operands, bool emit, int *count)
}
if (count)
*count = 2;
-
}
}
@@ -14087,7 +14433,7 @@ output_move_neon (rtx *operands)
ops[0] = XEXP (addr, 0);
ops[1] = reg;
break;
-
+
case POST_MODIFY:
/* FIXME: Not currently enabled in neon_vector_mem_operand. */
gcc_unreachable ();
@@ -14579,7 +14925,7 @@ arm_compute_save_reg0_reg12_mask (void)
}
-/* Compute the number of bytes used to store the static chain register on the
+/* Compute the number of bytes used to store the static chain register on the
stack, above the stack frame. We need to know this accurately to get the
alignment of the rest of the stack frame correct. */
@@ -14918,7 +15264,7 @@ output_return_instruction (rtx operand, int really_return, int reverse)
then try to pop r3 instead. */
if (stack_adjust)
live_regs_mask |= 1 << 3;
-
+
if (TARGET_UNIFIED_ASM)
sprintf (instr, "ldmfd%s\t%%|sp, {", conditional);
else
@@ -15132,7 +15478,7 @@ arm_output_epilogue (rtx sibling)
/* If we have already generated the return instruction
then it is futile to generate anything else. */
- if (use_return_insn (FALSE, sibling) &&
+ if (use_return_insn (FALSE, sibling) &&
(cfun->machine->return_used_this_function != 0))
return "";
@@ -15340,7 +15686,7 @@ arm_output_epilogue (rtx sibling)
{
operands[0] = stack_pointer_rtx;
operands[1] = hard_frame_pointer_rtx;
-
+
operands[2] = GEN_INT (offsets->frame - offsets->saved_regs);
output_add_immediate (operands);
}
@@ -15388,7 +15734,7 @@ arm_output_epilogue (rtx sibling)
}
}
}
-
+
if (amount)
{
operands[1] = operands[0];
@@ -16020,7 +16366,7 @@ arm_get_frame_offsets (void)
{
int reg = -1;
- /* If it is safe to use r3, then do so. This sometimes
+ /* If it is safe to use r3, then do so. This sometimes
generates better code on Thumb-2 by avoiding the need to
use 32-bit push/pop instructions. */
if (! any_sibcall_uses_r3 ()
@@ -16466,7 +16812,7 @@ arm_expand_prologue (void)
&& TARGET_ARM)
{
rtx lr = gen_rtx_REG (SImode, LR_REGNUM);
-
+
emit_set_insn (lr, plus_constant (lr, -4));
}
@@ -16677,7 +17023,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
if (TARGET_UNIFIED_ASM)
arm_print_condition (stream);
break;
-
+
case '.':
/* The current condition code for a condition code setting instruction.
Preceded by 's' in unified syntax, otherwise followed by 's'. */
@@ -17204,7 +17550,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
of the target. */
align = MEM_ALIGN (x) >> 3;
memsize = MEM_SIZE (x);
-
+
/* Only certain alignment specifiers are supported by the hardware. */
if (memsize == 16 && (align % 32) == 0)
align_bits = 256;
@@ -17214,7 +17560,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
align_bits = 64;
else
align_bits = 0;
-
+
if (align_bits != 0)
asm_fprintf (stream, ":%d", align_bits);
@@ -17284,7 +17630,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
fprintf (stream, "d%d[%d]", regno/2, ((regno % 2) ? 2 : 0));
}
return;
-
+
default:
if (x == 0)
{
@@ -17323,7 +17669,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
fputs (":lower16:", stream);
x = XEXP (x, 0);
}
-
+
output_addr_const (stream, x);
break;
}
@@ -17537,8 +17883,8 @@ arm_elf_asm_cdtor (rtx symbol, int priority, bool is_ctor)
if (!TARGET_AAPCS_BASED)
{
- (is_ctor ?
- default_named_section_asm_out_constructor
+ (is_ctor ?
+ default_named_section_asm_out_constructor
: default_named_section_asm_out_destructor) (symbol, priority);
return;
}
@@ -17547,7 +17893,7 @@ arm_elf_asm_cdtor (rtx symbol, int priority, bool is_ctor)
if (priority != DEFAULT_INIT_PRIORITY)
{
char buf[18];
- sprintf (buf, "%s.%.5u",
+ sprintf (buf, "%s.%.5u",
is_ctor ? ".init_array" : ".fini_array",
priority);
s = get_section (buf, SECTION_WRITE, NULL_TREE);
@@ -17621,6 +17967,7 @@ arm_elf_asm_destructor (rtx symbol, int priority)
/* Returns the index of the ARM condition code string in
`arm_condition_codes', or ARM_NV if the comparison is invalid.
COMPARISON should be an rtx like `(eq (...) (...))'. */
+
enum arm_cond_code
maybe_get_arm_condition_code (rtx comparison)
{
@@ -18238,7 +18585,7 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
if (IS_IWMMXT_REGNUM (regno))
return VALID_IWMMXT_REG_MODE (mode);
}
-
+
/* We allow almost any value to be stored in the general registers.
Restrict doubleword quantities to even register pairs so that we can
use ldrd. Do not allow very large Neon structure opaque modes in
@@ -19423,7 +19770,7 @@ arm_init_neon_builtins (void)
} \
} \
while (0)
-
+
struct builtin_description
{
const unsigned int mask;
@@ -19439,7 +19786,7 @@ static const struct builtin_description bdesc_2arg[] =
#define IWMMXT_BUILTIN(code, string, builtin) \
{ FL_IWMMXT, CODE_FOR_##code, "__builtin_arm_" string, \
ARM_BUILTIN_##builtin, UNKNOWN, 0 },
-
+
IWMMXT_BUILTIN (addv8qi3, "waddb", WADDB)
IWMMXT_BUILTIN (addv4hi3, "waddh", WADDH)
IWMMXT_BUILTIN (addv2si3, "waddw", WADDW)
@@ -19498,10 +19845,10 @@ static const struct builtin_description bdesc_2arg[] =
IWMMXT_BUILTIN (iwmmxt_wunpckihw, "wunpckihw", WUNPCKIHW)
IWMMXT_BUILTIN (iwmmxt_wmadds, "wmadds", WMADDS)
IWMMXT_BUILTIN (iwmmxt_wmaddu, "wmaddu", WMADDU)
-
+
#define IWMMXT_BUILTIN2(code, builtin) \
{ FL_IWMMXT, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, UNKNOWN, 0 },
-
+
IWMMXT_BUILTIN2 (iwmmxt_wpackhss, WPACKHSS)
IWMMXT_BUILTIN2 (iwmmxt_wpackwss, WPACKWSS)
IWMMXT_BUILTIN2 (iwmmxt_wpackdss, WPACKDSS)
@@ -19535,7 +19882,7 @@ static const struct builtin_description bdesc_2arg[] =
IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
};
-
+
static const struct builtin_description bdesc_1arg[] =
{
IWMMXT_BUILTIN (iwmmxt_tmovmskb, "tmovmskb", TMOVMSKB)
@@ -19557,7 +19904,7 @@ static const struct builtin_description bdesc_1arg[] =
IWMMXT_BUILTIN (iwmmxt_wunpckelsh, "wunpckelsh", WUNPCKELSH)
IWMMXT_BUILTIN (iwmmxt_wunpckelsw, "wunpckelsw", WUNPCKELSW)
};
-
+
/* Set up all the iWMMXt builtins. This is not called if
TARGET_IWMMXT is zero. */
@@ -19681,7 +20028,7 @@ arm_init_iwmmxt_builtins (void)
= build_function_type_list (long_long_unsigned_type_node,
V4HI_type_node,V4HI_type_node,
NULL_TREE);
-
+
/* Normal vector binops. */
tree v8qi_ftype_v8qi_v8qi
= build_function_type_list (V8QI_type_node,
@@ -19697,7 +20044,7 @@ arm_init_iwmmxt_builtins (void)
long_long_unsigned_type_node,
long_long_unsigned_type_node,
NULL_TREE);
-
+
/* Add all builtins that are more or less simple operations on two
operands. */
for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
@@ -20652,7 +20999,7 @@ number_of_first_bit_set (unsigned mask)
return ctz_hwi (mask);
}
-/* Like emit_multi_reg_push, but allowing for a different set of
+/* Like emit_multi_reg_push, but allowing for a different set of
registers to be described as saved. MASK is the set of registers
to be saved; REAL_REGS is the set of registers to be described as
saved. If REAL_REGS is 0, only describe the stack adjustment. */
@@ -22274,9 +22621,9 @@ arm_file_start (void)
if (arm_fpu_desc->model == ARM_FP_MODEL_VFP)
{
if (TARGET_HARD_FLOAT)
- asm_fprintf (asm_out_file, "\t.eabi_attribute 27, 3\n");
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_HardFP_use, 27, 3);
if (TARGET_HARD_FLOAT_ABI)
- asm_fprintf (asm_out_file, "\t.eabi_attribute 28, 1\n");
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_VFP_args, 28, 1);
}
}
asm_fprintf (asm_out_file, "\t.fpu %s\n", fpu_name);
@@ -22285,30 +22632,23 @@ arm_file_start (void)
are used. However we don't have any easy way of figuring this out.
Conservatively record the setting that would have been used. */
- /* Tag_ABI_FP_rounding. */
if (flag_rounding_math)
- asm_fprintf (asm_out_file, "\t.eabi_attribute 19, 1\n");
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_FP_rounding, 19, 1);
+
if (!flag_unsafe_math_optimizations)
{
- /* Tag_ABI_FP_denomal. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 20, 1\n");
- /* Tag_ABI_FP_exceptions. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 21, 1\n");
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_FP_denormal, 20, 1);
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_FP_exceptions, 21, 1);
}
- /* Tag_ABI_FP_user_exceptions. */
if (flag_signaling_nans)
- asm_fprintf (asm_out_file, "\t.eabi_attribute 22, 1\n");
- /* Tag_ABI_FP_number_model. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 23, %d\n",
- flag_finite_math_only ? 1 : 3);
-
- /* Tag_ABI_align8_needed. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 24, 1\n");
- /* Tag_ABI_align8_preserved. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 25, 1\n");
- /* Tag_ABI_enum_size. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 26, %d\n",
- flag_short_enums ? 1 : 2);
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_FP_user_exceptions, 22, 1);
+
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_FP_number_model, 23,
+ flag_finite_math_only ? 1 : 3);
+
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_align8_needed, 24, 1);
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_align8_preserved, 25, 1);
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_enum_size, 26, flag_short_enums ? 1 : 2);
/* Tag_ABI_optimization_goals. */
if (optimize_size)
@@ -22319,21 +22659,18 @@ arm_file_start (void)
val = 1;
else
val = 6;
- asm_fprintf (asm_out_file, "\t.eabi_attribute 30, %d\n", val);
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_optimization_goals, 30, val);
- /* Tag_CPU_unaligned_access. */
- asm_fprintf (asm_out_file, "\t.eabi_attribute 34, %d\n",
- unaligned_access);
+ EMIT_EABI_ATTRIBUTE (Tag_CPU_unaligned_access, 34, unaligned_access);
- /* Tag_ABI_FP_16bit_format. */
if (arm_fp16_format)
- asm_fprintf (asm_out_file, "\t.eabi_attribute 38, %d\n",
- (int)arm_fp16_format);
+ EMIT_EABI_ATTRIBUTE (Tag_ABI_FP_16bit_format, 38, (int) arm_fp16_format);
if (arm_lang_output_object_attributes_hook)
arm_lang_output_object_attributes_hook();
}
- default_file_start();
+
+ default_file_start ();
}
static void
@@ -22621,7 +22958,7 @@ arm_setup_incoming_varargs (cumulative_args_t pcum_v,
{
CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
int nregs;
-
+
cfun->machine->uses_anonymous_args = 1;
if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
{
@@ -22631,7 +22968,7 @@ arm_setup_incoming_varargs (cumulative_args_t pcum_v,
}
else
nregs = pcum->nregs;
-
+
if (nregs < NUM_ARG_REGS)
*pretend_size = (NUM_ARG_REGS - nregs) * UNITS_PER_WORD;
}
@@ -23131,7 +23468,7 @@ arm_preferred_simd_mode (enum machine_mode mode)
}
/* Implement TARGET_CLASS_LIKELY_SPILLED_P.
-
+
We need to define this for LO_REGS on Thumb-1. Otherwise we can end up
using r0-r4 for function arguments, r7 for the stack frame and don't have
enough left over to do doubleword arithmetic. For Thumb-2 all the
@@ -23699,7 +24036,7 @@ arm_output_shift(rtx * operands, int set_flags)
const char *shift;
HOST_WIDE_INT val;
char c;
-
+
c = flag_chars[set_flags];
if (TARGET_UNIFIED_ASM)
{
@@ -23730,10 +24067,10 @@ thumb1_output_casesi (rtx *operands)
switch (GET_MODE(diff_vec))
{
case QImode:
- return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned ?
+ return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned ?
"bl\t%___gnu_thumb1_case_uqi" : "bl\t%___gnu_thumb1_case_sqi");
case HImode:
- return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned ?
+ return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned ?
"bl\t%___gnu_thumb1_case_uhi" : "bl\t%___gnu_thumb1_case_shi");
case SImode:
return "bl\t%___gnu_thumb1_case_si";
@@ -23842,7 +24179,7 @@ arm_mangle_type (const_tree type)
/* The ARM ABI documents (10th October 2008) say that "__va_list"
has to be managled as if it is in the "std" namespace. */
- if (TARGET_AAPCS_BASED
+ if (TARGET_AAPCS_BASED
&& lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type))
{
static bool warned;
@@ -24039,12 +24376,26 @@ arm_output_ldrex (emit_f emit,
rtx target,
rtx memory)
{
- const char *suffix = arm_ldrex_suffix (mode);
- rtx operands[2];
+ rtx operands[3];
operands[0] = target;
- operands[1] = memory;
- arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix);
+ if (mode != DImode)
+ {
+ const char *suffix = arm_ldrex_suffix (mode);
+ operands[1] = memory;
+ arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix);
+ }
+ else
+ {
+ /* The restrictions on target registers in ARM mode are that the two
+ registers are consecutive and the first one is even; Thumb is
+ actually more flexible, but DI should give us this anyway.
+ Note that the 1st register always gets the lowest word in memory. */
+ gcc_assert ((REGNO (target) & 1) == 0);
+ operands[1] = gen_rtx_REG (SImode, REGNO (target) + 1);
+ operands[2] = memory;
+ arm_output_asm_insn (emit, 0, operands, "ldrexd\t%%0, %%1, %%C2");
+ }
}
/* Emit a strex{b,h,d, } instruction appropriate for the specified
@@ -24057,14 +24408,41 @@ arm_output_strex (emit_f emit,
rtx value,
rtx memory)
{
- const char *suffix = arm_ldrex_suffix (mode);
- rtx operands[3];
+ rtx operands[4];
operands[0] = result;
operands[1] = value;
- operands[2] = memory;
- arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2", suffix,
- cc);
+ if (mode != DImode)
+ {
+ const char *suffix = arm_ldrex_suffix (mode);
+ operands[2] = memory;
+ arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2",
+ suffix, cc);
+ }
+ else
+ {
+ /* The restrictions on target registers in ARM mode are that the two
+ registers are consecutive and the first one is even; Thumb is
+ actually more flexible, but DI should give us this anyway.
+ Note that the 1st register always gets the lowest word in memory. */
+ gcc_assert ((REGNO (value) & 1) == 0 || TARGET_THUMB2);
+ operands[2] = gen_rtx_REG (SImode, REGNO (value) + 1);
+ operands[3] = memory;
+ arm_output_asm_insn (emit, 0, operands, "strexd%s\t%%0, %%1, %%2, %%C3",
+ cc);
+ }
+}
+
+/* Helper to emit an it instruction in Thumb2 mode only; although the assembler
+ will ignore it in ARM mode, emitting it will mess up instruction counts we
+ sometimes keep 'flags' are the extra t's and e's if it's more than one
+ instruction that is conditional. */
+static void
+arm_output_it (emit_f emit, const char *flags, const char *cond)
+{
+ rtx operands[1]; /* Don't actually use the operand. */
+ if (TARGET_THUMB2)
+ arm_output_asm_insn (emit, 0, operands, "it%s\t%s", flags, cond);
}
/* Helper to emit a two operand instruction. */
@@ -24106,7 +24484,7 @@ arm_output_op3 (emit_f emit, const char *mnemonic, rtx d, rtx a, rtx b)
required_value:
- RTX register or const_int representing the required old_value for
+ RTX register representing the required old_value for
the modify to continue, if NULL no comparsion is performed. */
static void
arm_output_sync_loop (emit_f emit,
@@ -24120,7 +24498,13 @@ arm_output_sync_loop (emit_f emit,
enum attr_sync_op sync_op,
int early_barrier_required)
{
- rtx operands[1];
+ rtx operands[2];
+ /* We'll use the lo for the normal rtx in the none-DI case
+ as well as the least-sig word in the DI case. */
+ rtx old_value_lo, required_value_lo, new_value_lo, t1_lo;
+ rtx old_value_hi, required_value_hi, new_value_hi, t1_hi;
+
+ bool is_di = mode == DImode;
gcc_assert (t1 != t2);
@@ -24131,82 +24515,142 @@ arm_output_sync_loop (emit_f emit,
arm_output_ldrex (emit, mode, old_value, memory);
+ if (is_di)
+ {
+ old_value_lo = gen_lowpart (SImode, old_value);
+ old_value_hi = gen_highpart (SImode, old_value);
+ if (required_value)
+ {
+ required_value_lo = gen_lowpart (SImode, required_value);
+ required_value_hi = gen_highpart (SImode, required_value);
+ }
+ else
+ {
+ /* Silence false potentially unused warning. */
+ required_value_lo = NULL_RTX;
+ required_value_hi = NULL_RTX;
+ }
+ new_value_lo = gen_lowpart (SImode, new_value);
+ new_value_hi = gen_highpart (SImode, new_value);
+ t1_lo = gen_lowpart (SImode, t1);
+ t1_hi = gen_highpart (SImode, t1);
+ }
+ else
+ {
+ old_value_lo = old_value;
+ new_value_lo = new_value;
+ required_value_lo = required_value;
+ t1_lo = t1;
+
+ /* Silence false potentially unused warning. */
+ t1_hi = NULL_RTX;
+ new_value_hi = NULL_RTX;
+ required_value_hi = NULL_RTX;
+ old_value_hi = NULL_RTX;
+ }
+
if (required_value)
{
- rtx operands[2];
+ operands[0] = old_value_lo;
+ operands[1] = required_value_lo;
- operands[0] = old_value;
- operands[1] = required_value;
arm_output_asm_insn (emit, 0, operands, "cmp\t%%0, %%1");
+ if (is_di)
+ {
+ arm_output_it (emit, "", "eq");
+ arm_output_op2 (emit, "cmpeq", old_value_hi, required_value_hi);
+ }
arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYB%%=", LOCAL_LABEL_PREFIX);
}
switch (sync_op)
{
case SYNC_OP_ADD:
- arm_output_op3 (emit, "add", t1, old_value, new_value);
+ arm_output_op3 (emit, is_di ? "adds" : "add",
+ t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "adc", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_SUB:
- arm_output_op3 (emit, "sub", t1, old_value, new_value);
+ arm_output_op3 (emit, is_di ? "subs" : "sub",
+ t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "sbc", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_IOR:
- arm_output_op3 (emit, "orr", t1, old_value, new_value);
+ arm_output_op3 (emit, "orr", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "orr", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_XOR:
- arm_output_op3 (emit, "eor", t1, old_value, new_value);
+ arm_output_op3 (emit, "eor", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "eor", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_AND:
- arm_output_op3 (emit,"and", t1, old_value, new_value);
+ arm_output_op3 (emit,"and", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "and", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_NAND:
- arm_output_op3 (emit, "and", t1, old_value, new_value);
- arm_output_op2 (emit, "mvn", t1, t1);
+ arm_output_op3 (emit, "and", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "and", t1_hi, old_value_hi, new_value_hi);
+ arm_output_op2 (emit, "mvn", t1_lo, t1_lo);
+ if (is_di)
+ arm_output_op2 (emit, "mvn", t1_hi, t1_hi);
break;
case SYNC_OP_NONE:
t1 = new_value;
+ t1_lo = new_value_lo;
+ if (is_di)
+ t1_hi = new_value_hi;
break;
}
+ /* Note that the result of strex is a 0/1 flag that's always 1 register. */
if (t2)
{
- arm_output_strex (emit, mode, "", t2, t1, memory);
- operands[0] = t2;
- arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
- arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
- LOCAL_LABEL_PREFIX);
+ arm_output_strex (emit, mode, "", t2, t1, memory);
+ operands[0] = t2;
+ arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
+ LOCAL_LABEL_PREFIX);
}
else
{
/* Use old_value for the return value because for some operations
the old_value can easily be restored. This saves one register. */
- arm_output_strex (emit, mode, "", old_value, t1, memory);
- operands[0] = old_value;
+ arm_output_strex (emit, mode, "", old_value_lo, t1, memory);
+ operands[0] = old_value_lo;
arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
LOCAL_LABEL_PREFIX);
+ /* Note that we only used the _lo half of old_value as a temporary
+ so in DI we don't have to restore the _hi part. */
switch (sync_op)
{
case SYNC_OP_ADD:
- arm_output_op3 (emit, "sub", old_value, t1, new_value);
+ arm_output_op3 (emit, "sub", old_value_lo, t1_lo, new_value_lo);
break;
case SYNC_OP_SUB:
- arm_output_op3 (emit, "add", old_value, t1, new_value);
+ arm_output_op3 (emit, "add", old_value_lo, t1_lo, new_value_lo);
break;
case SYNC_OP_XOR:
- arm_output_op3 (emit, "eor", old_value, t1, new_value);
+ arm_output_op3 (emit, "eor", old_value_lo, t1_lo, new_value_lo);
break;
case SYNC_OP_NONE:
- arm_output_op2 (emit, "mov", old_value, required_value);
+ arm_output_op2 (emit, "mov", old_value_lo, required_value_lo);
break;
default:
@@ -24214,8 +24658,11 @@ arm_output_sync_loop (emit_f emit,
}
}
- arm_process_output_memory_barrier (emit, NULL);
+ /* Note: label is before barrier so that in cmp failure case we still get
+ a barrier to stop subsequent loads floating upwards past the ldrex
+ PR target/48126. */
arm_output_asm_insn (emit, 1, operands, "%sLSYB%%=:", LOCAL_LABEL_PREFIX);
+ arm_process_output_memory_barrier (emit, NULL);
}
static rtx
@@ -24309,7 +24756,7 @@ arm_expand_sync (enum machine_mode mode,
target = gen_reg_rtx (mode);
memory = arm_legitimize_sync_memory (memory);
- if (mode != SImode)
+ if (mode != SImode && mode != DImode)
{
rtx load_temp = gen_reg_rtx (SImode);
@@ -24368,7 +24815,7 @@ arm_builtin_support_vector_misalignment (enum machine_mode mode,
packed access. */
return ((misalignment % align) == 0);
}
-
+
return default_builtin_support_vector_misalignment (mode, type, misalignment,
is_packed);
}
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 993e3a07874..85e2b9971c4 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -288,7 +288,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
#define TARGET_HAVE_DMB (arm_arch7)
/* Nonzero if this chip implements a memory barrier via CP15. */
-#define TARGET_HAVE_DMB_MCR (arm_arch6k && ! TARGET_HAVE_DMB)
+#define TARGET_HAVE_DMB_MCR (arm_arch6 && ! TARGET_HAVE_DMB \
+ && ! TARGET_THUMB1)
/* Nonzero if this chip implements a memory barrier instruction. */
#define TARGET_HAVE_MEMORY_BARRIER (TARGET_HAVE_DMB || TARGET_HAVE_DMB_MCR)
@@ -296,8 +297,12 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
/* Nonzero if this chip supports ldrex and strex */
#define TARGET_HAVE_LDREX ((arm_arch6 && TARGET_ARM) || arm_arch7)
-/* Nonzero if this chip supports ldrex{bhd} and strex{bhd}. */
-#define TARGET_HAVE_LDREXBHD ((arm_arch6k && TARGET_ARM) || arm_arch7)
+/* Nonzero if this chip supports ldrex{bh} and strex{bh}. */
+#define TARGET_HAVE_LDREXBH ((arm_arch6k && TARGET_ARM) || arm_arch7)
+
+/* Nonzero if this chip supports ldrexd and strexd. */
+#define TARGET_HAVE_LDREXD (((arm_arch6k && TARGET_ARM) || arm_arch7) \
+ && arm_arch_notm)
/* Nonzero if integer division instructions supported. */
#define TARGET_IDIV ((TARGET_ARM && arm_arch_arm_hwdiv) \
@@ -2235,4 +2240,36 @@ extern int making_const_table;
" %{mcpu=generic-*:-march=%*;" \
" :%{mcpu=*:-mcpu=%*} %{march=*:-march=%*}}"
+/* This macro is used to emit an EABI tag and its associated value.
+ We emit the numerical value of the tag in case the assembler does not
+ support textual tags. (Eg gas prior to 2.20). If requested we include
+ the tag name in a comment so that anyone reading the assembler output
+ will know which tag is being set. */
+#define EMIT_EABI_ATTRIBUTE(NAME,NUM,VAL) \
+ do \
+ { \
+ asm_fprintf (asm_out_file, "\t.eabi_attribute %d, %d", NUM, VAL); \
+ if (flag_verbose_asm || flag_debug_asm) \
+ asm_fprintf (asm_out_file, "\t%s " #NAME, ASM_COMMENT_START); \
+ asm_fprintf (asm_out_file, "\n"); \
+ } \
+ while (0)
+
+/* -mcpu=native handling only makes sense with compiler running on
+ an ARM chip. */
+#if defined(__arm__)
+extern const char *host_detect_local_cpu (int argc, const char **argv);
+# define EXTRA_SPEC_FUNCTIONS \
+ { "local_cpu_detect", host_detect_local_cpu },
+
+# define MCPU_MTUNE_NATIVE_SPECS \
+ " %{march=native:%<march=native %:local_cpu_detect(arch)}" \
+ " %{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)}" \
+ " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}"
+#else
+# define MCPU_MTUNE_NATIVE_SPECS ""
+#endif
+
+#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS
+
#endif /* ! GCC_ARM_H */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index baa7eb41b4e..a78ba88f8ce 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -1213,27 +1213,24 @@
; ??? Check Thumb-2 split length
(define_insn_and_split "*arm_subsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r")
- (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r")
- (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r")
+ (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n")
+ (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r")))]
"TARGET_32BIT"
"@
rsb%?\\t%0, %2, %1
sub%?\\t%0, %1, %2
sub%?\\t%0, %1, %2
- #
#"
- "&& ((GET_CODE (operands[1]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[1])))
- || (GET_CODE (operands[2]) == CONST_INT
- && !const_ok_for_arm (INTVAL (operands[2]))))"
+ "&& (GET_CODE (operands[1]) == CONST_INT
+ && !const_ok_for_arm (INTVAL (operands[1])))"
[(clobber (const_int 0))]
"
arm_split_constant (MINUS, SImode, curr_insn,
INTVAL (operands[1]), operands[0], operands[2], 0);
DONE;
"
- [(set_attr "length" "4,4,4,16,16")
+ [(set_attr "length" "4,4,4,16")
(set_attr "predicable" "yes")]
)
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index e33b460520f..934aa35775e 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -80,6 +80,11 @@ march=
Target RejectNegative Joined Enum(arm_arch) Var(arm_arch_option)
Specify the name of the target architecture
+; Other arm_arch values are loaded from arm-tables.opt
+; but that is a generated file and this is an odd-one-out.
+EnumValue
+Enum(arm_arch) String(native) Value(-1) DriverOnly
+
marm
Target Report RejectNegative InverseMask(THUMB)
Generate code in 32 bit ARM state.
@@ -233,6 +238,11 @@ mtune=
Target RejectNegative Joined Enum(processor_type) Var(arm_tune_option) Init(arm_none)
Tune code for the given processor
+; Other processor_type values are loaded from arm-tables.opt
+; but that is a generated file and this is an odd-one-out.
+EnumValue
+Enum(processor_type) String(native) Value(-1) DriverOnly
+
mwords-little-endian
Target Report RejectNegative Mask(LITTLE_WORDS)
Assume big endian bytes, little endian words. This option is deprecated.
diff --git a/gcc/config/arm/driver-arm.c b/gcc/config/arm/driver-arm.c
new file mode 100644
index 00000000000..9a6762b4548
--- /dev/null
+++ b/gcc/config/arm/driver-arm.c
@@ -0,0 +1,149 @@
+/* Subroutines for the gcc driver.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "configargs.h"
+
+struct vendor_cpu {
+ const char *part_no;
+ const char *arch_name;
+ const char *cpu_name;
+};
+
+static struct vendor_cpu arm_cpu_table[] = {
+ {"0x926", "armv5te", "arm926ej-s"},
+ {"0xa26", "armv5te", "arm1026ej-s"},
+ {"0xb02", "armv6k", "mpcore"},
+ {"0xb36", "armv6j", "arm1136j-s"},
+ {"0xb56", "armv6t2", "arm1156t2-s"},
+ {"0xb76", "armv6zk", "arm1176jz-s"},
+ {"0xc05", "armv7-a", "cortex-a5"},
+ {"0xc08", "armv7-a", "cortex-a8"},
+ {"0xc09", "armv7-a", "cortex-a9"},
+ {"0xc0f", "armv7-a", "cortex-a15"},
+ {"0xc14", "armv7-r", "cortex-r4"},
+ {"0xc15", "armv7-r", "cortex-r5"},
+ {"0xc20", "armv6-m", "cortex-m0"},
+ {"0xc21", "armv6-m", "cortex-m1"},
+ {"0xc23", "armv7-m", "cortex-m3"},
+ {"0xc24", "armv7e-m", "cortex-m4"},
+ {NULL, NULL, NULL}
+};
+
+struct {
+ const char *vendor_no;
+ const struct vendor_cpu *vendor_parts;
+} vendors[] = {
+ {"0x41", arm_cpu_table},
+ {NULL, NULL}
+};
+
+/* This will be called by the spec parser in gcc.c when it sees
+ a %:local_cpu_detect(args) construct. Currently it will be called
+ with either "arch", "cpu" or "tune" as argument depending on if
+ -march=native, -mcpu=native or -mtune=native is to be substituted.
+
+ It returns a string containing new command line parameters to be
+ put at the place of the above two options, depending on what CPU
+ this is executed. E.g. "-march=armv7-a" on a Cortex-A8 for
+ -march=native. If the routine can't detect a known processor,
+ the -march or -mtune option is discarded.
+
+ ARGC and ARGV are set depending on the actual arguments given
+ in the spec. */
+const char *
+host_detect_local_cpu (int argc, const char **argv)
+{
+ const char *val = NULL;
+ char buf[128];
+ FILE *f = NULL;
+ bool arch;
+ const struct vendor_cpu *cpu_table = NULL;
+
+ if (argc < 1)
+ goto not_found;
+
+ arch = strcmp (argv[0], "arch") == 0;
+ if (!arch && strcmp (argv[0], "cpu") != 0 && strcmp (argv[0], "tune"))
+ goto not_found;
+
+ f = fopen ("/proc/cpuinfo", "r");
+ if (f == NULL)
+ goto not_found;
+
+ while (fgets (buf, sizeof (buf), f) != NULL)
+ {
+ /* Ensure that CPU implementer is ARM (0x41). */
+ if (strncmp (buf, "CPU implementer", sizeof ("CPU implementer") - 1) == 0)
+ {
+ int i;
+ for (i = 0; vendors[i].vendor_no != NULL; i++)
+ if (strstr (buf, vendors[i].vendor_no) != NULL)
+ {
+ cpu_table = vendors[i].vendor_parts;
+ break;
+ }
+ }
+
+ /* Detect arch/cpu. */
+ if (strncmp (buf, "CPU part", sizeof ("CPU part") - 1) == 0)
+ {
+ int i;
+
+ if (cpu_table == NULL)
+ goto not_found;
+
+ for (i = 0; cpu_table[i].part_no != NULL; i++)
+ if (strstr (buf, cpu_table[i].part_no) != NULL)
+ {
+ val = arch ? cpu_table[i].arch_name : cpu_table[i].cpu_name;
+ break;
+ }
+ break;
+ }
+ }
+
+ fclose (f);
+
+ if (val == NULL)
+ goto not_found;
+
+ return concat ("-m", argv[0], "=", val, NULL);
+
+not_found:
+ {
+ unsigned int i;
+ unsigned int opt;
+ const char *search[] = {NULL, "arch"};
+
+ if (f)
+ fclose (f);
+
+ search[0] = argv[0];
+ for (opt = 0; opt < ARRAY_SIZE (search); opt++)
+ for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
+ if (strcmp (configure_default_options[i].name, search[opt]) == 0)
+ return concat ("-m", search[opt], "=",
+ configure_default_options[i].value, NULL);
+ return NULL;
+ }
+}
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index da1f7af9b7a..08874ff0411 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -33,6 +33,15 @@
;; A list of integer modes that are up to one word long
(define_mode_iterator QHSI [QI HI SI])
+;; A list of integer modes that are less than a word
+(define_mode_iterator NARROW [QI HI])
+
+;; A list of all the integer modes upto 64bit
+(define_mode_iterator QHSD [QI HI SI DI])
+
+;; A list of the 32bit and 64bit integer modes
+(define_mode_iterator SIDI [SI DI])
+
;; Integer element sizes implemented by IWMMXT.
(define_mode_iterator VMMX [V2SI V4HI V8QI])
@@ -405,6 +414,9 @@
(V4QQ "8") (V2HQ "16") (QQ "8") (HQ "16")
(V2HA "16") (HA "16") (SQ "") (SA "")])
+;; Mode attribute for vshll.
+(define_mode_attr V_innermode [(V8QI "QI") (V4HI "HI") (V2SI "SI")])
+
;;----------------------------------------------------------------------------
;; Code attributes
;;----------------------------------------------------------------------------
diff --git a/gcc/config/arm/linux-atomic-64bit.c b/gcc/config/arm/linux-atomic-64bit.c
new file mode 100644
index 00000000000..af94c7f4ae5
--- /dev/null
+++ b/gcc/config/arm/linux-atomic-64bit.c
@@ -0,0 +1,166 @@
+/* 64bit Linux-specific atomic operations for ARM EABI.
+ Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Based on linux-atomic.c
+
+ 64 bit additions david.gilbert@linaro.org
+
+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/>. */
+
+/* 64bit helper functions for atomic operations; the compiler will
+ call these when the code is compiled for a CPU without ldrexd/strexd.
+ (If the CPU had those then the compiler inlines the operation).
+
+ These helpers require a kernel helper that's only present on newer
+ kernels; we check for that in an init section and bail out rather
+ unceremoneously. */
+
+extern unsigned int __write (int fd, const void *buf, unsigned int count);
+extern void abort (void);
+
+/* Kernel helper for compare-and-exchange. */
+typedef int (__kernel_cmpxchg64_t) (const long long* oldval,
+ const long long* newval,
+ long long *ptr);
+#define __kernel_cmpxchg64 (*(__kernel_cmpxchg64_t *) 0xffff0f60)
+
+/* Kernel helper page version number. */
+#define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
+
+/* Check that the kernel has a new enough version at load. */
+static void __check_for_sync8_kernelhelper (void)
+{
+ if (__kernel_helper_version < 5)
+ {
+ const char err[] = "A newer kernel is required to run this binary. "
+ "(__kernel_cmpxchg64 helper)\n";
+ /* At this point we need a way to crash with some information
+ for the user - I'm not sure I can rely on much else being
+ available at this point, so do the same as generic-morestack.c
+ write () and abort (). */
+ __write (2 /* stderr. */, err, sizeof (err));
+ abort ();
+ }
+};
+
+static void (*__sync8_kernelhelper_inithook[]) (void)
+ __attribute__ ((used, section (".init_array"))) = {
+ &__check_for_sync8_kernelhelper
+};
+
+#define HIDDEN __attribute__ ((visibility ("hidden")))
+
+#define FETCH_AND_OP_WORD64(OP, PFX_OP, INF_OP) \
+ long long HIDDEN \
+ __sync_fetch_and_##OP##_8 (long long *ptr, long long val) \
+ { \
+ int failure; \
+ long long tmp,tmp2; \
+ \
+ do { \
+ tmp = *ptr; \
+ tmp2 = PFX_OP (tmp INF_OP val); \
+ failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \
+ } while (failure != 0); \
+ \
+ return tmp; \
+ }
+
+FETCH_AND_OP_WORD64 (add, , +)
+FETCH_AND_OP_WORD64 (sub, , -)
+FETCH_AND_OP_WORD64 (or, , |)
+FETCH_AND_OP_WORD64 (and, , &)
+FETCH_AND_OP_WORD64 (xor, , ^)
+FETCH_AND_OP_WORD64 (nand, ~, &)
+
+#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
+#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
+
+/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
+ subword-sized quantities. */
+
+#define OP_AND_FETCH_WORD64(OP, PFX_OP, INF_OP) \
+ long long HIDDEN \
+ __sync_##OP##_and_fetch_8 (long long *ptr, long long val) \
+ { \
+ int failure; \
+ long long tmp,tmp2; \
+ \
+ do { \
+ tmp = *ptr; \
+ tmp2 = PFX_OP (tmp INF_OP val); \
+ failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \
+ } while (failure != 0); \
+ \
+ return tmp2; \
+ }
+
+OP_AND_FETCH_WORD64 (add, , +)
+OP_AND_FETCH_WORD64 (sub, , -)
+OP_AND_FETCH_WORD64 (or, , |)
+OP_AND_FETCH_WORD64 (and, , &)
+OP_AND_FETCH_WORD64 (xor, , ^)
+OP_AND_FETCH_WORD64 (nand, ~, &)
+
+long long HIDDEN
+__sync_val_compare_and_swap_8 (long long *ptr, long long oldval,
+ long long newval)
+{
+ int failure;
+ long long actual_oldval;
+
+ while (1)
+ {
+ actual_oldval = *ptr;
+
+ if (__builtin_expect (oldval != actual_oldval, 0))
+ return actual_oldval;
+
+ failure = __kernel_cmpxchg64 (&actual_oldval, &newval, ptr);
+
+ if (__builtin_expect (!failure, 1))
+ return oldval;
+ }
+}
+
+typedef unsigned char bool;
+
+bool HIDDEN
+__sync_bool_compare_and_swap_8 (long long *ptr, long long oldval,
+ long long newval)
+{
+ int failure = __kernel_cmpxchg64 (&oldval, &newval, ptr);
+ return (failure == 0);
+}
+
+long long HIDDEN
+__sync_lock_test_and_set_8 (long long *ptr, long long val)
+{
+ int failure;
+ long long oldval;
+
+ do {
+ oldval = *ptr;
+ failure = __kernel_cmpxchg64 (&oldval, &val, ptr);
+ } while (failure != 0);
+
+ return oldval;
+}
diff --git a/gcc/config/arm/linux-atomic.c b/gcc/config/arm/linux-atomic.c
index 57065a6e8a0..80f161d06a7 100644
--- a/gcc/config/arm/linux-atomic.c
+++ b/gcc/config/arm/linux-atomic.c
@@ -32,8 +32,8 @@ typedef void (__kernel_dmb_t) (void);
#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0)
/* Note: we implement byte, short and int versions of atomic operations using
- the above kernel helpers, but there is no support for "long long" (64-bit)
- operations as yet. */
+ the above kernel helpers; see linux-atomic-64bit.c for "long long" (64-bit)
+ operations. */
#define HIDDEN __attribute__ ((visibility ("hidden")))
@@ -273,6 +273,7 @@ SUBWORD_TEST_AND_SET (unsigned char, 1)
*ptr = 0; \
}
+SYNC_LOCK_RELEASE (long long, 8)
SYNC_LOCK_RELEASE (int, 4)
SYNC_LOCK_RELEASE (short, 2)
SYNC_LOCK_RELEASE (char, 1)
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index ea09da246ff..5cbe5bed2cc 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -5335,6 +5335,44 @@
}
)
+(define_insn "neon_vec_<US>shiftl_<mode>"
+ [(set (match_operand:<V_widen> 0 "register_operand" "=w")
+ (SE:<V_widen> (ashift:VW (match_operand:VW 1 "register_operand" "w")
+ (match_operand:<V_innermode> 2 "const_neon_scalar_shift_amount_operand" ""))))]
+ "TARGET_NEON"
+{
+ return "vshll.<US><V_sz_elem> %q0, %P1, %2";
+}
+ [(set_attr "neon_type" "neon_shift_1")]
+)
+
+(define_expand "vec_widen_<US>shiftl_lo_<mode>"
+ [(match_operand:<V_unpack> 0 "register_operand" "")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ {
+ emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
+ simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode, 0),
+ operands[2]));
+ DONE;
+ }
+)
+
+(define_expand "vec_widen_<US>shiftl_hi_<mode>"
+ [(match_operand:<V_unpack> 0 "register_operand" "")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ {
+ emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
+ simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
+ GET_MODE_SIZE (<V_HALF>mode)),
+ operands[2]));
+ DONE;
+ }
+)
+
;; Vectorize for non-neon-quad case
(define_insn "neon_unpack<US>_<mode>"
[(set (match_operand:<V_widen> 0 "register_operand" "=w")
@@ -5411,6 +5449,34 @@
}
)
+(define_expand "vec_widen_<US>shiftl_hi_<mode>"
+ [(match_operand:<V_double_width> 0 "register_operand" "")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON"
+ {
+ rtx tmpreg = gen_reg_rtx (<V_widen>mode);
+ emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
+ emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
+
+ DONE;
+ }
+)
+
+(define_expand "vec_widen_<US>shiftl_lo_<mode>"
+ [(match_operand:<V_double_width> 0 "register_operand" "")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON"
+ {
+ rtx tmpreg = gen_reg_rtx (<V_widen>mode);
+ emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
+ emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
+
+ DONE;
+ }
+)
+
; FIXME: These instruction patterns can't be used safely in big-endian mode
; because the ordering of vector elements in Q registers is different from what
; the semantics of the instructions require.
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 27ba6033f78..92eb004ae14 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -129,11 +129,17 @@
(ior (match_operand 0 "arm_rhs_operand")
(match_operand 0 "memory_operand")))
+;; This doesn't have to do much because the constant is already checked
+;; in the shift_operator predicate.
(define_predicate "shift_amount_operand"
(ior (and (match_test "TARGET_ARM")
(match_operand 0 "s_register_operand"))
- (and (match_code "const_int")
- (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 32"))))
+ (match_operand 0 "const_int_operand")))
+
+(define_predicate "const_neon_scalar_shift_amount_operand"
+ (and (match_code "const_int")
+ (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) <= GET_MODE_BITSIZE (mode)
+ && ((unsigned HOST_WIDE_INT) INTVAL (op)) > 0")))
(define_predicate "arm_add_operand"
(ior (match_operand 0 "arm_rhs_operand")
@@ -219,13 +225,20 @@
(match_test "mode == GET_MODE (op)")))
;; True for shift operators.
+;; Notes:
+;; * mult is only permitted with a constant shift amount
+;; * patterns that permit register shift amounts only in ARM mode use
+;; shift_amount_operand, patterns that always allow registers do not,
+;; so we don't have to worry about that sort of thing here.
(define_special_predicate "shift_operator"
(and (ior (ior (and (match_code "mult")
(match_test "power_of_two_operand (XEXP (op, 1), mode)"))
(and (match_code "rotate")
(match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
- (match_code "ashift,ashiftrt,lshiftrt,rotatert"))
+ (and (match_code "ashift,ashiftrt,lshiftrt,rotatert")
+ (match_test "GET_CODE (XEXP (op, 1)) != CONST_INT
+ || ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
(match_test "mode == GET_MODE (op)")))
;; True for shift operators which can be used with saturation instructions.
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index 689a235c16f..40ee93c35d1 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -1,6 +1,7 @@
;; Machine description for ARM processor synchronization primitives.
;; Copyright (C) 2010 Free Software Foundation, Inc.
;; Written by Marcus Shawcroft (marcus.shawcroft@arm.com)
+;; 64bit Atomics by Dave Gilbert (david.gilbert@linaro.org)
;;
;; This file is part of GCC.
;;
@@ -33,31 +34,24 @@
MEM_VOLATILE_P (operands[0]) = 1;
})
-(define_expand "sync_compare_and_swapsi"
- [(set (match_operand:SI 0 "s_register_operand")
- (unspec_volatile:SI [(match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (match_operand:SI 3 "s_register_operand")]
- VUNSPEC_SYNC_COMPARE_AND_SWAP))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omrn;
- generator.u.omrn = gen_arm_sync_compare_and_swapsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], operands[2],
- operands[3]);
- DONE;
- })
-(define_mode_iterator NARROW [QI HI])
+(define_mode_attr sync_predtab [(SI "TARGET_HAVE_LDREX &&
+ TARGET_HAVE_MEMORY_BARRIER")
+ (QI "TARGET_HAVE_LDREXBH &&
+ TARGET_HAVE_MEMORY_BARRIER")
+ (HI "TARGET_HAVE_LDREXBH &&
+ TARGET_HAVE_MEMORY_BARRIER")
+ (DI "TARGET_HAVE_LDREXD &&
+ ARM_DOUBLEWORD_ALIGN &&
+ TARGET_HAVE_MEMORY_BARRIER")])
(define_expand "sync_compare_and_swap<mode>"
- [(set (match_operand:NARROW 0 "s_register_operand")
- (unspec_volatile:NARROW [(match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (match_operand:NARROW 3 "s_register_operand")]
+ [(set (match_operand:QHSD 0 "s_register_operand")
+ (unspec_volatile:QHSD [(match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (match_operand:QHSD 3 "s_register_operand")]
VUNSPEC_SYNC_COMPARE_AND_SWAP))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omrn;
@@ -67,25 +61,11 @@
DONE;
})
-(define_expand "sync_lock_test_and_setsi"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_lock_test_and_setsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
(define_expand "sync_lock_test_and_set<mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -115,51 +95,25 @@
(plus "*")
(minus "*")])
-(define_expand "sync_<sync_optab>si"
- [(match_operand:SI 0 "memory_operand")
- (match_operand:SI 1 "s_register_operand")
- (syncop:SI (match_dup 0) (match_dup 1))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_<sync_optab>si;
- arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
- DONE;
- })
-
-(define_expand "sync_nandsi"
- [(match_operand:SI 0 "memory_operand")
- (match_operand:SI 1 "s_register_operand")
- (not:SI (and:SI (match_dup 0) (match_dup 1)))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_nandsi;
- arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
- DONE;
- })
-
(define_expand "sync_<sync_optab><mode>"
- [(match_operand:NARROW 0 "memory_operand")
- (match_operand:NARROW 1 "s_register_operand")
- (syncop:NARROW (match_dup 0) (match_dup 1))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "memory_operand")
+ (match_operand:QHSD 1 "s_register_operand")
+ (syncop:QHSD (match_dup 0) (match_dup 1))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
- operands[1]);
+ operands[1]);
DONE;
})
(define_expand "sync_nand<mode>"
- [(match_operand:NARROW 0 "memory_operand")
- (match_operand:NARROW 1 "s_register_operand")
- (not:NARROW (and:NARROW (match_dup 0) (match_dup 1)))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "memory_operand")
+ (match_operand:QHSD 1 "s_register_operand")
+ (not:QHSD (and:QHSD (match_dup 0) (match_dup 1)))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -169,57 +123,27 @@
DONE;
})
-(define_expand "sync_new_<sync_optab>si"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (syncop:SI (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_<sync_optab>si;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
-(define_expand "sync_new_nandsi"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (not:SI (and:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_nandsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
(define_expand "sync_new_<sync_optab><mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (syncop:NARROW (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (syncop:QHSD (match_dup 1) (match_dup 2))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
- NULL, operands[2]);
+ NULL, operands[2]);
DONE;
})
(define_expand "sync_new_nand<mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (not:QHSD (and:QHSD (match_dup 1) (match_dup 2)))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -229,57 +153,27 @@
DONE;
});
-(define_expand "sync_old_<sync_optab>si"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (syncop:SI (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_old_<sync_optab>si;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
-(define_expand "sync_old_nandsi"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (not:SI (and:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_old_nandsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
(define_expand "sync_old_<sync_optab><mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (syncop:NARROW (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (syncop:QHSD (match_dup 1) (match_dup 2))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
generator.u.omn = gen_arm_sync_old_<sync_optab><mode>;
arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
- NULL, operands[2]);
+ NULL, operands[2]);
DONE;
})
(define_expand "sync_old_nand<mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (not:QHSD (and:QHSD (match_dup 1) (match_dup 2)))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -289,22 +183,22 @@
DONE;
})
-(define_insn "arm_sync_compare_and_swapsi"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI
- [(match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "s_register_operand" "r")]
- VUNSPEC_SYNC_COMPARE_AND_SWAP))
- (set (match_dup 1) (unspec_volatile:SI [(match_dup 2)]
+(define_insn "arm_sync_compare_and_swap<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI
+ [(match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r")
+ (match_operand:SIDI 3 "s_register_operand" "r")]
+ VUNSPEC_SYNC_COMPARE_AND_SWAP))
+ (set (match_dup 1) (unspec_volatile:SIDI [(match_dup 2)]
VUNSPEC_SYNC_COMPARE_AND_SWAP))
(set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
VUNSPEC_SYNC_COMPARE_AND_SWAP))
]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_required_value" "2")
@@ -318,7 +212,7 @@
(zero_extend:SI
(unspec_volatile:NARROW
[(match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 2 "s_register_operand" "r")
(match_operand:SI 3 "s_register_operand" "r")]
VUNSPEC_SYNC_COMPARE_AND_SWAP)))
(set (match_dup 1) (unspec_volatile:NARROW [(match_dup 2)]
@@ -326,10 +220,10 @@
(set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
VUNSPEC_SYNC_COMPARE_AND_SWAP))
]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_required_value" "2")
@@ -338,18 +232,18 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_lock_test_and_setsi"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q"))
+(define_insn "arm_sync_lock_test_and_set<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q"))
(set (match_dup 1)
- (unspec_volatile:SI [(match_operand:SI 2 "s_register_operand" "r")]
- VUNSPEC_SYNC_LOCK))
+ (unspec_volatile:SIDI [(match_operand:SIDI 2 "s_register_operand" "r")]
+ VUNSPEC_SYNC_LOCK))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_release_barrier" "no")
(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
@@ -364,10 +258,10 @@
(zero_extend:SI (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")))
(set (match_dup 1)
(unspec_volatile:NARROW [(match_operand:SI 2 "s_register_operand" "r")]
- VUNSPEC_SYNC_LOCK))
+ VUNSPEC_SYNC_LOCK))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -380,22 +274,22 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_new_<sync_optab>si"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_NEW_OP))
+(define_insn "arm_sync_new_<sync_optab><mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(syncop:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
@@ -405,54 +299,54 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_new_nandsi"
+(define_insn "arm_sync_new_<sync_optab><mode>"
[(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(not:SI (and:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")))
- ]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:SI [(syncop:SI
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "0")
(set_attr "sync_t2" "3")
- (set_attr "sync_op" "nand")
+ (set_attr "sync_op" "<sync_optab>")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_new_<sync_optab><mode>"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_NEW_OP))
+(define_insn "arm_sync_new_nand<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(not:SIDI (and:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r")))
+ ]
+ VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
- (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "0")
(set_attr "sync_t2" "3")
- (set_attr "sync_op" "<sync_optab>")
+ (set_attr "sync_op" "nand")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
@@ -461,19 +355,19 @@
(unspec_volatile:SI
[(not:SI
(and:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r")))
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r")))
] VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
(unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
@@ -483,20 +377,20 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_old_<sync_optab>si"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_OLD_OP))
+(define_insn "arm_sync_old_<sync_optab><mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(syncop:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:SI 3 "=&r"))
+ (clobber (match_scratch:SIDI 3 "=&r"))
(clobber (match_scratch:SI 4 "<sync_clobber>"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -509,20 +403,21 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_old_nandsi"
+(define_insn "arm_sync_old_<sync_optab><mode>"
[(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(not:SI (and:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")))
- ]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:SI [(syncop:SI
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))
- (clobber (match_scratch:SI 4 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ (clobber (match_scratch:SI 4 "<sync_clobber>"))]
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -530,26 +425,25 @@
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "3")
- (set_attr "sync_t2" "4")
- (set_attr "sync_op" "nand")
+ (set_attr "sync_t2" "<sync_t2_reqd>")
+ (set_attr "sync_op" "<sync_optab>")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_old_<sync_optab><mode>"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_OLD_OP))
+(define_insn "arm_sync_old_nand<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(not:SIDI (and:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r")))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:SI 3 "=&r"))
- (clobber (match_scratch:SI 4 "<sync_clobber>"))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ (clobber (match_scratch:SIDI 3 "=&r"))
+ (clobber (match_scratch:SI 4 "=&r"))]
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -557,26 +451,26 @@
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "3")
- (set_attr "sync_t2" "<sync_t2_reqd>")
- (set_attr "sync_op" "<sync_optab>")
+ (set_attr "sync_t2" "4")
+ (set_attr "sync_op" "nand")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
(define_insn "arm_sync_old_nand<mode>"
[(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(not:SI (and:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r")))
- ]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:SI [(not:SI (and:SI
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r")))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))
(clobber (match_scratch:SI 4 "=&r"))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
diff --git a/gcc/config/arm/t-linux-eabi b/gcc/config/arm/t-linux-eabi
index a328a000552..3814cc09b81 100644
--- a/gcc/config/arm/t-linux-eabi
+++ b/gcc/config/arm/t-linux-eabi
@@ -36,3 +36,4 @@ LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx _clear_cache
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
LIB2FUNCS_STATIC_EXTRA += $(srcdir)/config/arm/linux-atomic.c
+LIB2FUNCS_STATIC_EXTRA += $(srcdir)/config/arm/linux-atomic-64bit.c
diff --git a/gcc/config/arm/x-arm b/gcc/config/arm/x-arm
new file mode 100644
index 00000000000..51cff1ed48b
--- /dev/null
+++ b/gcc/config/arm/x-arm
@@ -0,0 +1,3 @@
+driver-arm.o: $(srcdir)/config/arm/driver-arm.c \
+ $(CONFIG_H) $(SYSTEM_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
index 4a592da9849..51203584042 100644
--- a/gcc/config/avr/avr-mcus.def
+++ b/gcc/config/avr/avr-mcus.def
@@ -117,7 +117,7 @@ AVR_MCU ("atmega16a", ARCH_AVR5, "__AVR_ATmega16A__", 0, 0, 0
AVR_MCU ("atmega161", ARCH_AVR5, "__AVR_ATmega161__", 0, 0, 0x0060, "m161")
AVR_MCU ("atmega162", ARCH_AVR5, "__AVR_ATmega162__", 0, 0, 0x0100, "m162")
AVR_MCU ("atmega163", ARCH_AVR5, "__AVR_ATmega163__", 0, 0, 0x0060, "m163")
-AVR_MCU ("atmega164a", ARCH_AVR5, "__AVR_ATmega164A__", 0, 0, 0x0060, "m164a")
+AVR_MCU ("atmega164a", ARCH_AVR5, "__AVR_ATmega164A__", 0, 0, 0x0100, "m164a")
AVR_MCU ("atmega164p", ARCH_AVR5, "__AVR_ATmega164P__", 0, 0, 0x0100, "m164p")
AVR_MCU ("atmega165", ARCH_AVR5, "__AVR_ATmega165__", 0, 0, 0x0100, "m165")
AVR_MCU ("atmega165a", ARCH_AVR5, "__AVR_ATmega165A__", 0, 0, 0x0100, "m165a")
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 91e51088917..dd8ba3a3318 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -82,7 +82,9 @@ extern void avr_output_bld (rtx operands[], int bit_nr);
extern void avr_output_addr_vec_elt (FILE *stream, int value);
extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
extern const char* avr_out_bitop (rtx, rtx*, int*);
-extern const char* avr_out_plus (rtx*, int*);
+extern const char* avr_out_plus (rtx*, int*, int*);
+extern const char* avr_out_plus_noclobber (rtx*, int*, int*);
+extern const char* avr_out_addto_sp (rtx*, int*);
extern bool avr_popcount_each_byte (rtx, int, int);
extern int extra_constraint_Q (rtx x);
@@ -105,7 +107,10 @@ extern int avr_simplify_comparison_p (enum machine_mode mode,
extern RTX_CODE avr_normalize_condition (RTX_CODE condition);
extern void out_shift_with_cnt (const char *templ, rtx insn,
rtx operands[], int *len, int t_len);
+extern reg_class_t avr_mode_code_base_reg_class (enum machine_mode, RTX_CODE, RTX_CODE);
+extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, RTX_CODE, RTX_CODE);
extern rtx avr_incoming_return_addr_rtx (void);
+extern rtx avr_legitimize_reload_address (rtx, enum machine_mode, int, int, int, int, rtx (*)(rtx,int));
#endif /* RTX_CODE */
#ifdef REAL_VALUE_TYPE
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 55fbae4649e..94bc30af3d9 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -351,6 +351,28 @@ avr_option_override (void)
{
flag_delete_null_pointer_checks = 0;
+ /* caller-save.c looks for call-clobbered hard registers that are assigned
+ to pseudos that cross calls and tries so save-restore them around calls
+ in order to reduce the number of stack slots needed.
+
+ This might leads to situations where reload is no more able to cope
+ with the challenge of AVR's very few address registers and fails to
+ perform the requested spills. */
+
+ if (avr_strict_X)
+ flag_caller_saves = 0;
+
+ /* Unwind tables currently require a frame pointer for correctness,
+ see toplev.c:process_options(). */
+
+ if ((flag_unwind_tables
+ || flag_non_call_exceptions
+ || flag_asynchronous_unwind_tables)
+ && !ACCUMULATE_OUTGOING_ARGS)
+ {
+ flag_omit_frame_pointer = 0;
+ }
+
avr_current_device = &avr_mcu_types[avr_mcu_index];
avr_current_arch = &avr_arch_types[avr_current_device->arch];
avr_extra_arch_macro = avr_current_device->macro;
@@ -1029,9 +1051,10 @@ expand_epilogue (bool sibcall_p)
if (frame_pointer_needed)
{
/* Get rid of frame. */
- emit_move_insn(frame_pointer_rtx,
- gen_rtx_PLUS (HImode, frame_pointer_rtx,
- gen_int_mode (size, HImode)));
+ if (size)
+ emit_move_insn (frame_pointer_rtx,
+ gen_rtx_PLUS (HImode, frame_pointer_rtx,
+ gen_int_mode (size, HImode)));
}
else
{
@@ -1187,52 +1210,89 @@ avr_cannot_modify_jumps_p (void)
}
+/* Helper function for `avr_legitimate_address_p'. */
+
+static inline bool
+avr_reg_ok_for_addr_p (rtx reg, addr_space_t as ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code, bool strict)
+{
+ return (REG_P (reg)
+ && (avr_regno_mode_code_ok_for_base_p (REGNO (reg),
+ QImode, outer_code, UNKNOWN)
+ || (!strict
+ && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
+}
+
+
/* Return nonzero if X (an RTX) is a legitimate memory address on the target
machine for a memory operand of mode MODE. */
-bool
+static bool
avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
- reg_class_t r = NO_REGS;
+ bool ok = CONSTANT_ADDRESS_P (x);
- if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
- : REG_OK_FOR_BASE_NOSTRICT_P (x)))
- r = POINTER_REGS;
- else if (CONSTANT_ADDRESS_P (x))
- r = ALL_REGS;
- else if (GET_CODE (x) == PLUS
- && REG_P (XEXP (x, 0))
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) >= 0)
- {
- int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
- if (fit)
- {
- if (! strict
- || REGNO (XEXP (x,0)) == REG_X
- || REGNO (XEXP (x,0)) == REG_Y
- || REGNO (XEXP (x,0)) == REG_Z)
- r = BASE_POINTER_REGS;
- if (XEXP (x,0) == frame_pointer_rtx
- || XEXP (x,0) == arg_pointer_rtx)
- r = BASE_POINTER_REGS;
- }
- else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
- r = POINTER_Y_REGS;
- }
- else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
- && REG_P (XEXP (x, 0))
- && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
- : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
+ switch (GET_CODE (x))
{
- r = POINTER_REGS;
- }
+ case REG:
+ ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
+ MEM, strict);
+
+ if (strict
+ && DImode == mode
+ && REG_X == REGNO (x))
+ {
+ ok = false;
+ }
+ break;
+ case POST_INC:
+ case PRE_DEC:
+ ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
+ GET_CODE (x), strict);
+ break;
+
+ case PLUS:
+ {
+ rtx reg = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+
+ if (REG_P (reg)
+ && CONST_INT_P (op1)
+ && INTVAL (op1) >= 0)
+ {
+ bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
+
+ if (fit)
+ {
+ ok = (! strict
+ || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
+ PLUS, strict));
+
+ if (reg == frame_pointer_rtx
+ || reg == arg_pointer_rtx)
+ {
+ ok = true;
+ }
+ }
+ else if (frame_pointer_needed
+ && reg == frame_pointer_rtx)
+ {
+ ok = true;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
if (avr_log.legitimate_address_p)
{
- avr_edump ("\n%?: ret=%d=%R, mode=%m strict=%d "
+ avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
"reload_completed=%d reload_in_progress=%d %s:",
- !!r, r, mode, strict, reload_completed, reload_in_progress,
+ ok, mode, strict, reload_completed, reload_in_progress,
reg_renumber ? "(reg_renumber)" : "");
if (GET_CODE (x) == PLUS
@@ -1248,13 +1308,13 @@ avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
avr_edump ("\n%r\n", x);
}
- return r == NO_REGS ? 0 : (int)r;
+ return ok;
}
/* Attempts to replace X with a valid
memory address for an operand of mode MODE */
-rtx
+static rtx
avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
{
bool big_offset_p = false;
@@ -1290,6 +1350,87 @@ avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
}
+/* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
+/* This will allow register R26/27 to be used where it is no worse than normal
+ base pointers R28/29 or R30/31. For example, if base offset is greater
+ than 63 bytes or for R++ or --R addressing. */
+
+rtx
+avr_legitimize_reload_address (rtx x, enum machine_mode mode,
+ int opnum, int type, int addr_type,
+ int ind_levels ATTRIBUTE_UNUSED,
+ rtx (*mk_memloc)(rtx,int))
+{
+ if (avr_log.legitimize_reload_address)
+ avr_edump ("\n%?:%m %r\n", mode, x);
+
+ if (1 && (GET_CODE (x) == POST_INC
+ || GET_CODE (x) == PRE_DEC))
+ {
+ push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
+ POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
+ opnum, RELOAD_OTHER);
+
+ if (avr_log.legitimize_reload_address)
+ avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
+
+ return x;
+ }
+
+ if (GET_CODE (x) == PLUS
+ && REG_P (XEXP (x, 0))
+ && 0 == reg_equiv_constant (REGNO (XEXP (x, 0)))
+ && CONST_INT_P (XEXP (x, 1))
+ && INTVAL (XEXP (x, 1)) >= 1)
+ {
+ bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
+
+ if (fit)
+ {
+ if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
+ {
+ int regno = REGNO (XEXP (x, 0));
+ rtx mem = mk_memloc (x, regno);
+
+ push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
+ POINTER_REGS, Pmode, VOIDmode, 0, 0,
+ 1, addr_type);
+
+ if (avr_log.legitimize_reload_address)
+ avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ POINTER_REGS, XEXP (mem, 0), NULL_RTX);
+
+ push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
+ BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, type);
+
+ if (avr_log.legitimize_reload_address)
+ avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ BASE_POINTER_REGS, mem, NULL_RTX);
+
+ return x;
+ }
+ }
+ else if (! (frame_pointer_needed
+ && XEXP (x, 0) == frame_pointer_rtx))
+ {
+ push_reload (x, NULL_RTX, &x, NULL,
+ POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, type);
+
+ if (avr_log.legitimize_reload_address)
+ avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ POINTER_REGS, x, NULL_RTX);
+
+ return x;
+ }
+ }
+
+ return NULL_RTX;
+}
+
+
/* Helper function to print assembler resp. track instruction
sequence lengths.
@@ -1534,9 +1675,42 @@ void
notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
{
rtx set;
+ enum attr_cc cc = get_attr_cc (insn);
- switch (get_attr_cc (insn))
+ switch (cc)
+ {
+ default:
+ break;
+
+ case CC_OUT_PLUS:
+ case CC_OUT_PLUS_NOCLOBBER:
+ {
+ rtx *op = recog_data.operand;
+ int len_dummy, icc;
+
+ /* Extract insn's operands. */
+ extract_constrain_insn_cached (insn);
+
+ if (CC_OUT_PLUS == cc)
+ avr_out_plus (op, &len_dummy, &icc);
+ else
+ avr_out_plus_noclobber (op, &len_dummy, &icc);
+
+ cc = (enum attr_cc) icc;
+
+ break;
+ }
+ }
+
+ switch (cc)
{
+ default:
+ /* Special values like CC_OUT_PLUS from above have been
+ mapped to "standard" CC_* values so we never come here. */
+
+ gcc_unreachable();
+ break;
+
case CC_NONE:
/* Insn does not affect CC at all. */
break;
@@ -4577,10 +4751,11 @@ lshrsi3_out (rtx insn, rtx operands[], int *len)
addition; otherwise, set *PLEN to the length of the instruction sequence (in
words) printed with PLEN == NULL. XOP[3] is an 8-bit scratch register.
CODE == PLUS: perform addition by using ADD instructions.
- CODE == MINUS: perform addition by using SUB instructions. */
+ CODE == MINUS: perform addition by using SUB instructions.
+ Set *PCC to effect on cc0 according to respective CC_* insn attribute. */
static void
-avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
+avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
{
/* MODE of the operation. */
enum machine_mode mode = GET_MODE (xop[0]);
@@ -4604,6 +4779,11 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
/* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
rtx xval = xop[2];
+ /* Except in the case of ADIW with 16-bit register (see below)
+ addition does not set cc0 in a usable way. */
+
+ *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
+
if (MINUS == code)
xval = gen_int_mode (-UINTVAL (xval), mode);
@@ -4626,6 +4806,11 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
op[0] = reg8;
op[1] = GEN_INT (val8);
+
+ /* To get usable cc0 no low-bytes must have been skipped. */
+
+ if (i && !started)
+ *pcc = CC_CLOBBER;
if (!started && i % 2 == 0
&& test_hard_reg_class (ADDW_REGS, reg8))
@@ -4643,6 +4828,9 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
started = true;
avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
op, plen, 1);
+
+ if (n_bytes == 2 && PLUS == code)
+ *pcc = CC_SET_ZN;
}
i++;
@@ -4658,6 +4846,14 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
op, plen, 1);
continue;
}
+ else if ((val8 == 1 || val8 == 0xff)
+ && !started
+ && i == n_bytes - 1)
+ {
+ avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
+ op, plen, 1);
+ break;
+ }
switch (code)
{
@@ -4698,6 +4894,11 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
started = true;
} /* for all sub-bytes */
+
+ /* No output doesn't change cc0. */
+
+ if (plen && *plen == 0)
+ *pcc = CC_NONE;
}
@@ -4707,29 +4908,56 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
and return "". If PLEN == NULL, print assembler instructions to perform the
addition; otherwise, set *PLEN to the length of the instruction sequence (in
- words) printed with PLEN == NULL. */
+ words) printed with PLEN == NULL.
+ If PCC != 0 then set *PCC to the the instruction sequence's effect on the
+ condition code (with respect to XOP[0]). */
const char*
-avr_out_plus (rtx *xop, int *plen)
+avr_out_plus (rtx *xop, int *plen, int *pcc)
{
int len_plus, len_minus;
+ int cc_plus, cc_minus, cc_dummy;
+ if (!pcc)
+ pcc = &cc_dummy;
+
/* Work out if XOP[0] += XOP[2] is better or XOP[0] -= -XOP[2]. */
- avr_out_plus_1 (xop, &len_plus, PLUS);
- avr_out_plus_1 (xop, &len_minus, MINUS);
+ avr_out_plus_1 (xop, &len_plus, PLUS, &cc_plus);
+ avr_out_plus_1 (xop, &len_minus, MINUS, &cc_minus);
+ /* Prefer MINUS over PLUS if size is equal because it sets cc0. */
+
if (plen)
- *plen = (len_minus <= len_plus) ? len_minus : len_plus;
+ {
+ *plen = (len_minus <= len_plus) ? len_minus : len_plus;
+ *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
+ }
else if (len_minus <= len_plus)
- avr_out_plus_1 (xop, NULL, MINUS);
+ avr_out_plus_1 (xop, NULL, MINUS, pcc);
else
- avr_out_plus_1 (xop, NULL, PLUS);
+ avr_out_plus_1 (xop, NULL, PLUS, pcc);
return "";
}
+/* Same as above but XOP has just 3 entries.
+ Supply a dummy 4th operand. */
+
+const char*
+avr_out_plus_noclobber (rtx *xop, int *plen, int *pcc)
+{
+ rtx op[4];
+
+ op[0] = xop[0];
+ op[1] = xop[1];
+ op[2] = xop[2];
+ op[3] = NULL_RTX;
+
+ return avr_out_plus (op, plen, pcc);
+}
+
/* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
time constant XOP[2]:
@@ -4880,6 +5108,47 @@ avr_out_bitop (rtx insn, rtx *xop, int *plen)
return "";
}
+
+/* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
+ PLEN != NULL: Set *PLEN to the length of that sequence.
+ Return "". */
+
+const char*
+avr_out_addto_sp (rtx *op, int *plen)
+{
+ int pc_len = AVR_2_BYTE_PC ? 2 : 3;
+ int addend = INTVAL (op[0]);
+
+ if (plen)
+ *plen = 0;
+
+ if (addend < 0)
+ {
+ if (flag_verbose_asm || flag_print_asm_name)
+ avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
+
+ while (addend <= -pc_len)
+ {
+ addend += pc_len;
+ avr_asm_len ("rcall .", op, plen, 1);
+ }
+
+ while (addend++ < 0)
+ avr_asm_len ("push __zero_reg__", op, plen, 1);
+ }
+ else if (addend > 0)
+ {
+ if (flag_verbose_asm || flag_print_asm_name)
+ avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
+
+ while (addend-- > 0)
+ avr_asm_len ("pop __tmp_reg__", op, plen, 1);
+ }
+
+ return "";
+}
+
+
/* Create RTL split patterns for byte sized rotate expressions. This
produces a series of move instructions and considers overlap situations.
Overlapping non-HImode operands need a scratch register. */
@@ -5072,7 +5341,11 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
- case ADJUST_LEN_OUT_PLUS: avr_out_plus (op, &len); break;
+ case ADJUST_LEN_OUT_PLUS: avr_out_plus (op, &len, NULL); break;
+ case ADJUST_LEN_OUT_PLUS_NOCLOBBER:
+ avr_out_plus_noclobber (op, &len, NULL); break;
+
+ case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
@@ -5094,6 +5367,8 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
+ case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
+
default:
gcc_unreachable();
}
@@ -6984,6 +7259,53 @@ test_hard_reg_class (enum reg_class rclass, rtx x)
}
+/* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
+ and thus is suitable to be skipped by CPSE, SBRC, etc. */
+
+static bool
+avr_2word_insn_p (rtx insn)
+{
+ if (avr_current_device->errata_skip
+ || !insn
+ || 2 != get_attr_length (insn))
+ {
+ return false;
+ }
+
+ switch (INSN_CODE (insn))
+ {
+ default:
+ return false;
+
+ case CODE_FOR_movqi_insn:
+ {
+ rtx set = single_set (insn);
+ rtx src = SET_SRC (set);
+ rtx dest = SET_DEST (set);
+
+ /* Factor out LDS and STS from movqi_insn. */
+
+ if (MEM_P (dest)
+ && (REG_P (src) || src == const0_rtx))
+ {
+ return CONSTANT_ADDRESS_P (XEXP (dest, 0));
+ }
+ else if (REG_P (dest)
+ && MEM_P (src))
+ {
+ return CONSTANT_ADDRESS_P (XEXP (src, 0));
+ }
+
+ return false;
+ }
+
+ case CODE_FOR_call_insn:
+ case CODE_FOR_call_value_insn:
+ return true;
+ }
+}
+
+
int
jump_over_one_insn_p (rtx insn, rtx dest)
{
@@ -6992,7 +7314,11 @@ jump_over_one_insn_p (rtx insn, rtx dest)
: dest);
int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
int dest_addr = INSN_ADDRESSES (uid);
- return dest_addr - jump_addr == get_attr_length (insn) + 1;
+ int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
+
+ return (jump_offset == 1
+ || (jump_offset == 2
+ && avr_2word_insn_p (next_active_insn (insn))));
}
/* Returns 1 if a value of mode MODE can be stored starting with hard
@@ -7031,6 +7357,62 @@ avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
}
+/* Implement `MODE_CODE_BASE_REG_CLASS'. */
+
+reg_class_t
+avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code,
+ RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+ if (!avr_strict_X)
+ return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
+
+ return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
+}
+
+
+/* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
+
+bool
+avr_regno_mode_code_ok_for_base_p (int regno,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code,
+ RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+ bool ok = false;
+
+ if (regno < FIRST_PSEUDO_REGISTER
+ && (regno == REG_X
+ || regno == REG_Y
+ || regno == REG_Z
+ || regno == ARG_POINTER_REGNUM))
+ {
+ ok = true;
+ }
+ else if (reg_renumber)
+ {
+ regno = reg_renumber[regno];
+
+ if (regno == REG_X
+ || regno == REG_Y
+ || regno == REG_Z
+ || regno == ARG_POINTER_REGNUM)
+ {
+ ok = true;
+ }
+ }
+
+ if (avr_strict_X
+ && PLUS == outer_code
+ && regno == REG_X)
+ {
+ ok = false;
+ }
+
+ return ok;
+}
+
+
/* A helper for `output_reload_insisf' and `output_reload_inhi'. */
/* Set 32-bit register OP[0] to compile-time constant OP[1].
CLOBBER_REG is a QI clobber register or NULL_RTX.
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index dbb0b4c207a..1a5f20a0e13 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -308,21 +308,13 @@ enum reg_class {
#define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
-#define BASE_REG_CLASS (reload_completed ? BASE_POINTER_REGS : POINTER_REGS)
+#define MODE_CODE_BASE_REG_CLASS(mode, outer_code, index_code) \
+ avr_mode_code_base_reg_class (mode, outer_code, index_code)
#define INDEX_REG_CLASS NO_REGS
-#define REGNO_OK_FOR_BASE_P(r) (((r) < FIRST_PSEUDO_REGISTER \
- && ((r) == REG_X \
- || (r) == REG_Y \
- || (r) == REG_Z \
- || (r) == ARG_POINTER_REGNUM)) \
- || (reg_renumber \
- && (reg_renumber[r] == REG_X \
- || reg_renumber[r] == REG_Y \
- || reg_renumber[r] == REG_Z \
- || (reg_renumber[r] \
- == ARG_POINTER_REGNUM))))
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, outer_code, index_code) \
+ avr_regno_mode_code_ok_for_base_p (num, mode, outer_code, index_code)
#define REGNO_OK_FOR_INDEX_P(NUM) 0
@@ -381,55 +373,17 @@ typedef struct avr_args {
#define MAX_REGS_PER_ADDRESS 1
-#define REG_OK_FOR_BASE_NOSTRICT_P(X) \
- (REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
-
-#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-
-/* LEGITIMIZE_RELOAD_ADDRESS will allow register R26/27 to be used, where it
- is no worse than normal base pointers R28/29 and R30/31. For example:
- If base offset is greater than 63 bytes or for R++ or --R addressing. */
-
-#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
-do { \
- if (1&&(GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC)) \
- { \
- push_reload (XEXP (X,0), XEXP (X,0), &XEXP (X,0), &XEXP (X,0), \
- POINTER_REGS, GET_MODE (X),GET_MODE (X) , 0, 0, \
- OPNUM, RELOAD_OTHER); \
- goto WIN; \
- } \
- if (GET_CODE (X) == PLUS \
- && REG_P (XEXP (X, 0)) \
- && (reg_equiv_constant (REGNO (XEXP (X, 0))) == 0) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && INTVAL (XEXP (X, 1)) >= 1) \
- { \
- int fit = INTVAL (XEXP (X, 1)) <= (64 - GET_MODE_SIZE (MODE)); \
- if (fit) \
- { \
- if (reg_equiv_address (REGNO (XEXP (X, 0))) != 0) \
- { \
- int regno = REGNO (XEXP (X, 0)); \
- rtx mem = make_memloc (X, regno); \
- push_reload (XEXP (mem,0), NULL, &XEXP (mem,0), NULL, \
- POINTER_REGS, Pmode, VOIDmode, 0, 0, \
- 1, ADDR_TYPE (TYPE)); \
- push_reload (mem, NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_POINTER_REGS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
- } \
- else if (! (frame_pointer_needed && XEXP (X,0) == frame_pointer_rtx)) \
- { \
- push_reload (X, NULL_RTX, &X, NULL, \
- POINTER_REGS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
- } \
-} while(0)
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
+ do { \
+ rtx new_x = avr_legitimize_reload_address (X, MODE, OPNUM, TYPE, \
+ ADDR_TYPE (TYPE), \
+ IND_L, make_memloc); \
+ if (new_x) \
+ { \
+ X = new_x; \
+ goto WIN; \
+ } \
+ } while (0)
#define BRANCH_COST(speed_p, predictable_p) 0
@@ -500,8 +454,6 @@ do { \
#define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X)
-#define ASSEMBLER_DIALECT AVR_HAVE_MOVW
-
#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \
{ \
gcc_assert (REGNO < 32); \
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 3b1800d3fb0..35d4bdc1717 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -77,23 +77,13 @@
(include "constraints.md")
;; Condition code settings.
-(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber"
+(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
+ out_plus, out_plus_noclobber"
(const_string "none"))
(define_attr "type" "branch,branch1,arith,xcall"
(const_string "arith"))
-(define_attr "mcu_have_movw" "yes,no"
- (const (if_then_else (symbol_ref "AVR_HAVE_MOVW")
- (const_string "yes")
- (const_string "no"))))
-
-(define_attr "mcu_mega" "yes,no"
- (const (if_then_else (symbol_ref "AVR_HAVE_JMP_CALL")
- (const_string "yes")
- (const_string "no"))))
-
-
;; The size of instructions in bytes.
;; XXX may depend from "cc"
@@ -123,7 +113,7 @@
(const_int 3)
(const_int 4)))
(eq_attr "type" "xcall")
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 1)
(const_int 2))]
(const_int 2)))
@@ -132,11 +122,11 @@
;; Following insn attribute tells if and how the adjustment has to be
;; done:
;; no No adjustment needed; attribute "length" is fine.
-;; yes Analyse pattern in adjust_insn_length by hand.
;; Otherwise do special processing depending on the attribute.
(define_attr "adjust_len"
- "out_bitop, out_plus, tsthi, tstsi, compare,
+ "out_bitop, out_plus, out_plus_noclobber, addto_sp,
+ tsthi, tstsi, compare, call,
mov8, mov16, mov32, reload_in16, reload_in32,
ashlqi, ashrqi, lshrqi,
ashlhi, ashrhi, lshrhi,
@@ -144,6 +134,50 @@
no"
(const_string "no"))
+;; Flavours of instruction set architecture (ISA), used in enabled attribute
+
+;; mov: ISA has no MOVW
+;; movw: ISA has MOVW
+;; rjmp: ISA has no CALL/JMP
+;; jmp: ISA has CALL/JMP
+;; ijmp: ISA has no EICALL/EIJMP
+;; eijmp: ISA has EICALL/EIJMP
+
+(define_attr "isa"
+ "mov,movw, rjmp,jmp, ijmp,eijmp,
+ standard"
+ (const_string "standard"))
+
+(define_attr "enabled" ""
+ (cond [(eq_attr "isa" "standard")
+ (const_int 1)
+
+ (and (eq_attr "isa" "mov")
+ (match_test "!AVR_HAVE_MOVW"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "movw")
+ (match_test "AVR_HAVE_MOVW"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "rjmp")
+ (match_test "!AVR_HAVE_JMP_CALL"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "jmp")
+ (match_test "AVR_HAVE_JMP_CALL"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "ijmp")
+ (match_test "!AVR_HAVE_EIJMP_EICALL"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "eijmp")
+ (match_test "AVR_HAVE_EIJMP_EICALL"))
+ (const_int 1)
+ ] (const_int 0)))
+
+
;; Define mode iterators
(define_mode_iterator QIHI [(QI "") (HI "")])
(define_mode_iterator QIHI2 [(QI "") (HI "")])
@@ -295,7 +329,7 @@
operands[1] = copy_to_mode_reg(QImode, operand1);
")
-(define_insn "*movqi"
+(define_insn "movqi_insn"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
(match_operand:QI 1 "general_operand" "rL,i,rL,Qm,r,q,i"))]
"(register_operand (operands[0],QImode)
@@ -346,15 +380,6 @@
}
}")
-(define_insn "*movhi_sp"
- [(set (match_operand:HI 0 "register_operand" "=q,r")
- (match_operand:HI 1 "register_operand" "r,q"))]
- "((stack_register_operand(operands[0], HImode) && register_operand (operands[1], HImode))
- || (register_operand (operands[0], HImode) && stack_register_operand(operands[1], HImode)))"
- "* return output_movhi (insn, operands, NULL);"
- [(set_attr "length" "5,2")
- (set_attr "cc" "none,none")])
-
(define_insn "movhi_sp_r_irq_off"
[(set (match_operand:HI 0 "stack_register_operand" "=q")
(unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r")]
@@ -735,14 +760,22 @@
(plus:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))]
""
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- short tmp = INTVAL (operands[2]);
- operands[2] = GEN_INT(tmp);
- }
-}")
+ {
+ if (CONST_INT_P (operands[2]))
+ {
+ operands[2] = gen_int_mode (INTVAL (operands[2]), HImode);
+
+ if (can_create_pseudo_p()
+ && !stack_register_operand (operands[0], HImode)
+ && !stack_register_operand (operands[1], HImode)
+ && !d_register_operand (operands[0], HImode)
+ && !d_register_operand (operands[1], HImode))
+ {
+ emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ }
+ })
(define_insn "*addhi3_zero_extend"
@@ -767,184 +800,113 @@
[(set_attr "length" "2")
(set_attr "cc" "set_n")])
-(define_insn "*addhi3_sp_R_pc2"
+(define_insn "*addhi3_sp_R"
[(set (match_operand:HI 1 "stack_register_operand" "=q")
(plus:HI (match_operand:HI 2 "stack_register_operand" "q")
(match_operand:HI 0 "avr_sp_immediate_operand" "R")))]
- "AVR_2_BYTE_PC"
- "*{
- if (CONST_INT_P (operands[0]))
- {
- switch(INTVAL (operands[0]))
- {
- case -6:
- return \"rcall .\" CR_TAB
- \"rcall .\" CR_TAB
- \"rcall .\";
- case -5:
- return \"rcall .\" CR_TAB
- \"rcall .\" CR_TAB
- \"push __tmp_reg__\";
- case -4:
- return \"rcall .\" CR_TAB
- \"rcall .\";
- case -3:
- return \"rcall .\" CR_TAB
- \"push __tmp_reg__\";
- case -2:
- return \"rcall .\";
- case -1:
- return \"push __tmp_reg__\";
- case 0:
- return \"\";
- case 1:
- return \"pop __tmp_reg__\";
- case 2:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- case 3:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- case 4:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- case 5:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- }
- }
- return \"bug\";
- }"
- [(set (attr "length")
- (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
- (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
- (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
- (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
- (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
- (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
- (eq (const_int 0) (symbol_ref "INTVAL (operands[0])")) (const_int 0)
- (eq (const_int 1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
- (eq (const_int 2) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
- (eq (const_int 3) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
- (eq (const_int 4) (symbol_ref "INTVAL (operands[0])")) (const_int 4)
- (eq (const_int 5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)]
- (const_int 0)))])
-
-(define_insn "*addhi3_sp_R_pc3"
- [(set (match_operand:HI 1 "stack_register_operand" "=q")
- (plus:HI (match_operand:HI 2 "stack_register_operand" "q")
- (match_operand:QI 0 "avr_sp_immediate_operand" "R")))]
- "AVR_3_BYTE_PC"
- "*{
- if (CONST_INT_P (operands[0]))
- {
- switch(INTVAL (operands[0]))
- {
- case -6:
- return \"rcall .\" CR_TAB
- \"rcall .\";
- case -5:
- return \"rcall .\" CR_TAB
- \"push __tmp_reg__\" CR_TAB
- \"push __tmp_reg__\";
- case -4:
- return \"rcall .\" CR_TAB
- \"push __tmp_reg__\";
- case -3:
- return \"rcall .\";
- case -2:
- return \"push __tmp_reg__\" CR_TAB
- \"push __tmp_reg__\";
- case -1:
- return \"push __tmp_reg__\";
- case 0:
- return \"\";
- case 1:
- return \"pop __tmp_reg__\";
- case 2:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- case 3:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- case 4:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- case 5:
- return \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\" CR_TAB
- \"pop __tmp_reg__\";
- }
- }
- return \"bug\";
- }"
- [(set (attr "length")
- (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
- (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
- (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
- (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
- (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
- (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
- (eq (const_int 0) (symbol_ref "INTVAL (operands[0])")) (const_int 0)
- (eq (const_int 1) (symbol_ref "INTVAL (operands[0])")) (const_int 1)
- (eq (const_int 2) (symbol_ref "INTVAL (operands[0])")) (const_int 2)
- (eq (const_int 3) (symbol_ref "INTVAL (operands[0])")) (const_int 3)
- (eq (const_int 4) (symbol_ref "INTVAL (operands[0])")) (const_int 4)
- (eq (const_int 5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)]
- (const_int 0)))])
+ ""
+ {
+ return avr_out_addto_sp (operands, NULL);
+ }
+ [(set_attr "length" "5")
+ (set_attr "adjust_len" "addto_sp")])
(define_insn "*addhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,!w,!w,d,r,r")
- (plus:HI
- (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:HI 2 "nonmemory_operand" "r,I,J,i,P,N")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,d,d")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+ (match_operand:HI 2 "nonmemory_operand" "r,s,n")))]
""
- "@
- add %A0,%A2\;adc %B0,%B2
- adiw %A0,%2
- sbiw %A0,%n2
- subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))
- sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__
- sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__"
- [(set_attr "length" "2,1,1,2,3,3")
- (set_attr "cc" "set_n,set_czn,set_czn,set_czn,set_n,set_n")])
+ {
+ static const char * const asm_code[] =
+ {
+ "add %A0,%A2\;adc %B0,%B2",
+ "subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))",
+ ""
+ };
+
+ if (*asm_code[which_alternative])
+ return asm_code[which_alternative];
+
+ return avr_out_plus_noclobber (operands, NULL, NULL);
+ }
+ [(set_attr "length" "2,2,2")
+ (set_attr "adjust_len" "*,*,out_plus_noclobber")
+ (set_attr "cc" "set_n,set_czn,out_plus_noclobber")])
+
+;; Adding a constant to NO_LD_REGS might have lead to a reload of
+;; that constant to LD_REGS. We don't add a scratch to *addhi3
+;; itself because that insn is special to reload.
+
+(define_peephole2 ; addhi3_clobber
+ [(set (match_operand:HI 0 "d_register_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
+ (set (match_operand:HI 2 "l_register_operand" "")
+ (plus:HI (match_dup 2)
+ (match_dup 0)))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_dup 2)
+ (plus:HI (match_dup 2)
+ (match_dup 1)))
+ (clobber (match_dup 3))])]
+ {
+ operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
+ })
+
+;; Same, but with reload to NO_LD_REGS
+;; Combine *reload_inhi with *addhi3
+
+(define_peephole2 ; addhi3_clobber
+ [(parallel [(set (match_operand:HI 0 "l_register_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
+ (clobber (match_operand:QI 2 "d_register_operand" ""))])
+ (set (match_operand:HI 3 "l_register_operand" "")
+ (plus:HI (match_dup 3)
+ (match_dup 0)))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_dup 3)
+ (plus:HI (match_dup 3)
+ (match_dup 1)))
+ (clobber (match_dup 2))])])
+
+(define_insn "addhi3_clobber"
+ [(set (match_operand:HI 0 "register_operand" "=d,l")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "const_int_operand" "n,n")))
+ (clobber (match_scratch:QI 3 "=X,&d"))]
+ ""
+ {
+ gcc_assert (REGNO (operands[0]) == REGNO (operands[1]));
+
+ return avr_out_plus (operands, NULL, NULL);
+ }
+ [(set_attr "length" "4")
+ (set_attr "adjust_len" "out_plus")
+ (set_attr "cc" "out_plus")])
+
(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,!w,!w,d,l,l ,d,r")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0 ,0,0,0 ,0,0")
- (match_operand:SI 2 "nonmemory_operand" "r,I ,J ,s,P,N ,n,n")))
- (clobber (match_scratch:QI 3 "=X,X ,X ,X,X,X ,X,&d"))]
+ [(set (match_operand:SI 0 "register_operand" "=r,d ,d,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,s ,n,n")))
+ (clobber (match_scratch:QI 3 "=X,X ,X,&d"))]
""
{
static const char * const asm_code[] =
{
"add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2\;adc %D0,%D2",
- "adiw %0,%2\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__",
- "sbiw %0,%n2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__",
"subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))\;sbci %D0,hhi8(-(%2))",
- "sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__",
- "sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
+ "",
+ ""
};
- if (which_alternative >= (signed) (sizeof (asm_code) / sizeof (*asm_code)))
- return avr_out_plus (operands, NULL);
+ if (*asm_code[which_alternative])
+ return asm_code [which_alternative];
- return asm_code [which_alternative];
+ return avr_out_plus (operands, NULL, NULL);
}
- [(set_attr "length" "4,3,3,4,5,5,8,8")
- (set_attr "adjust_len" "*,*,*,*,*,*,out_plus,out_plus")
- (set_attr "cc" "set_n,set_n,set_czn,set_czn,set_n,set_n,clobber,clobber")])
+ [(set_attr "length" "4,4,4,8")
+ (set_attr "adjust_len" "*,*,out_plus,out_plus")
+ (set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
(define_insn "*addsi3_zero_extend"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1695,13 +1657,11 @@
(mult:HI (match_operand:HI 1 "register_operand" "r")
(match_operand:HI 2 "register_operand" "r")))]
"AVR_HAVE_MUL"
- "mul %A1,%A2
- movw %0,r0
- mul %A1,%B2
- add %B0,r0
- mul %B1,%A2
- add %B0,r0
- clr r1"
+ {
+ return REGNO (operands[1]) == REGNO (operands[2])
+ ? "mul %A1,%A1\;movw %0,r0\;mul %A1,%B1\;add %B0,r0\;add %B0,r0\;clr r1"
+ : "mul %A1,%A2\;movw %0,r0\;mul %A1,%B2\;add %B0,r0\;mul %B1,%A2\;add %B0,r0\;clr r1";
+ }
[(set_attr "length" "7")
(set_attr "cc" "clobber")])
@@ -3087,20 +3047,17 @@
(set_attr "cc" "set_czn,set_n,set_czn")])
(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=!d,r,&r")
- (neg:SI (match_operand:SI 1 "register_operand" "0,0,r")))]
+ [(set (match_operand:SI 0 "register_operand" "=!d,r,&r,&r")
+ (neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))]
""
"@
com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1)
com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__
- clr %A0\;clr %B0\;{clr %C0\;clr %D0|movw %C0,%A0}\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
- [(set_attr_alternative "length"
- [(const_int 7)
- (const_int 8)
- (if_then_else (eq_attr "mcu_have_movw" "yes")
- (const_int 7)
- (const_int 8))])
- (set_attr "cc" "set_czn,set_n,set_czn")])
+ clr %A0\;clr %B0\;clr %C0\;clr %D0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1
+ clr %A0\;clr %B0\;movw %C0,%A0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
+ [(set_attr "length" "7,8,8,7")
+ (set_attr "isa" "*,*,mov,movw")
+ (set_attr "cc" "set_czn,set_n,set_czn,set_czn")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=d,r")
@@ -3174,18 +3131,16 @@
(set_attr "cc" "set_n,set_n")])
(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r ,r")
+ (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
""
"@
clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
- {mov %A0,%A1\;mov %B0,%B1|movw %A0,%A1}\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
- [(set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (eq_attr "mcu_have_movw" "yes")
- (const_int 5)
- (const_int 6))])
- (set_attr "cc" "set_n,set_n")])
+ mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
+ movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
+ [(set_attr "length" "4,6,5")
+ (set_attr "isa" "*,mov,movw")
+ (set_attr "cc" "set_n")])
;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
;; zero extend
@@ -3494,7 +3449,7 @@
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
(le (minus (pc) (match_dup 3)) (const_int 2046)))
(const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 2)
(const_int 4))))
(set_attr "cc" "clobber")])
@@ -3524,7 +3479,7 @@
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
(le (minus (pc) (match_dup 3)) (const_int 2046)))
(const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 2)
(const_int 4))))
(set_attr "cc" "clobber")])
@@ -3707,20 +3662,20 @@
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
- "*{
- if (AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1)
- return AS1 (jmp,%x0);
- return AS1 (rjmp,%x0);
-}"
+ {
+ return AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1
+ ? "jmp %x0"
+ : "rjmp %x0";
+ }
[(set (attr "length")
(if_then_else (match_operand 0 "symbol_ref_operand" "")
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 1)
- (const_int 2))
- (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047))
- (le (minus (pc) (match_dup 0)) (const_int 2047)))
- (const_int 1)
- (const_int 2))))
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 1)
+ (const_int 2))
+ (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047))
+ (le (minus (pc) (match_dup 0)) (const_int 2047)))
+ (const_int 1)
+ (const_int 2))))
(set_attr "cc" "none")])
;; call
@@ -3765,7 +3720,7 @@
""
"")
-(define_insn "*call_insn"
+(define_insn "call_insn"
[(parallel[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "z,s,z,s"))
(match_operand:HI 1 "general_operand" "X,X,X,X"))
(use (match_operand:HI 2 "const_int_operand" "L,L,P,P"))])]
@@ -3778,17 +3733,10 @@
%!ijmp
%~jmp %x0"
[(set_attr "cc" "clobber")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))
- (const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))])])
+ (set_attr "length" "1,*,1,*")
+ (set_attr "adjust_len" "*,call,*,call")])
-(define_insn "*call_value_insn"
+(define_insn "call_value_insn"
[(parallel[(set (match_operand 0 "register_operand" "=r,r,r,r")
(call (mem:HI (match_operand:HI 1 "nonmemory_operand" "z,s,z,s"))
(match_operand:HI 2 "general_operand" "X,X,X,X")))
@@ -3802,15 +3750,8 @@
%!ijmp
%~jmp %x1"
[(set_attr "cc" "clobber")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))
- (const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))])])
+ (set_attr "length" "1,*,1,*")
+ (set_attr "adjust_len" "*,call,*,call")])
(define_insn "nop"
[(const_int 0)]
@@ -3822,96 +3763,52 @@
; indirect jump
(define_expand "indirect_jump"
- [(set (pc) (match_operand:HI 0 "nonmemory_operand" ""))]
+ [(set (pc)
+ (match_operand:HI 0 "nonmemory_operand" ""))]
""
- " if ((!AVR_HAVE_JMP_CALL) && !register_operand(operand0, HImode))
- {
- operands[0] = copy_to_mode_reg(HImode, operand0);
- }"
-)
+ {
+ if (!AVR_HAVE_JMP_CALL && !register_operand (operands[0], HImode))
+ {
+ operands[0] = copy_to_mode_reg (HImode, operands[0]);
+ }
+ })
; indirect jump
-(define_insn "*jcindirect_jump"
- [(set (pc) (match_operand:HI 0 "immediate_operand" "i"))]
+(define_insn "*indirect_jump"
+ [(set (pc)
+ (match_operand:HI 0 "nonmemory_operand" "i,i,!z,*r,z"))]
""
- "%~jmp %x0"
- [(set_attr "length" "2")
- (set_attr "cc" "none")])
-
-;;
-(define_insn "*njcindirect_jump"
- [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))]
- "!AVR_HAVE_EIJMP_EICALL"
"@
+ rjmp %x0
+ jmp %x0
ijmp
- push %A0\;push %B0\;ret"
- [(set_attr "length" "1,3")
- (set_attr "cc" "none,none")])
-
-(define_insn "*indirect_jump_avr6"
- [(set (pc) (match_operand:HI 0 "register_operand" "z"))]
- "AVR_HAVE_EIJMP_EICALL"
- "eijmp"
- [(set_attr "length" "1")
+ push %A0\;push %B0\;ret
+ eijmp"
+ [(set_attr "length" "1,2,1,3,1")
+ (set_attr "isa" "rjmp,jmp,ijmp,ijmp,eijmp")
(set_attr "cc" "none")])
;; table jump
+;; For entries in jump table see avr_output_addr_vec_elt.
-;; Table made from "rjmp" instructions for <=8K devices.
-(define_insn "*tablejump_rjmp"
- [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")]
- UNSPEC_INDEX_JMP))
+;; Table made from
+;; "rjmp .L<n>" instructions for <= 8K devices
+;; ".word gs(.L<n>)" addresses for > 8K devices
+(define_insn "*tablejump"
+ [(set (pc)
+ (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")]
+ UNSPEC_INDEX_JMP))
(use (label_ref (match_operand 1 "" "")))
(clobber (match_dup 0))]
- "(!AVR_HAVE_JMP_CALL) && (!AVR_HAVE_EIJMP_EICALL)"
+ ""
"@
ijmp
- push %A0\;push %B0\;ret"
- [(set_attr "length" "1,3")
- (set_attr "cc" "none,none")])
-
-;; Not a prologue, but similar idea - move the common piece of code to libgcc.
-(define_insn "*tablejump_lib"
- [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
- UNSPEC_INDEX_JMP))
- (use (label_ref (match_operand 1 "" "")))
- (clobber (match_dup 0))]
- "AVR_HAVE_JMP_CALL && TARGET_CALL_PROLOGUES"
- "%~jmp __tablejump2__"
- [(set_attr "length" "2")
- (set_attr "cc" "clobber")])
+ push %A0\;push %B0\;ret
+ jmp __tablejump2__"
+ [(set_attr "length" "1,3,2")
+ (set_attr "isa" "rjmp,rjmp,jmp")
+ (set_attr "cc" "none,none,clobber")])
-(define_insn "*tablejump_enh"
- [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
- UNSPEC_INDEX_JMP))
- (use (label_ref (match_operand 1 "" "")))
- (clobber (match_dup 0))]
- "AVR_HAVE_JMP_CALL && AVR_HAVE_LPMX"
- "lsl r30
- rol r31
- lpm __tmp_reg__,Z+
- lpm r31,Z
- mov r30,__tmp_reg__
- %!ijmp"
- [(set_attr "length" "6")
- (set_attr "cc" "clobber")])
-
-(define_insn "*tablejump"
- [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
- UNSPEC_INDEX_JMP))
- (use (label_ref (match_operand 1 "" "")))
- (clobber (match_dup 0))]
- "AVR_HAVE_JMP_CALL && !AVR_HAVE_EIJMP_EICALL"
- "lsl r30
- rol r31
- lpm
- inc r30
- push r0
- lpm
- push r0
- ret"
- [(set_attr "length" "8")
- (set_attr "cc" "clobber")])
(define_expand "casesi"
[(set (match_dup 6)
@@ -3993,11 +3890,11 @@
"* return avr_out_sbxx_branch (insn, operands);"
[(set (attr "length")
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
- (le (minus (pc) (match_dup 3)) (const_int 2046)))
- (const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 2)
- (const_int 4))))
+ (le (minus (pc) (match_dup 3)) (const_int 2046)))
+ (const_int 2)
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 2)
+ (const_int 4))))
(set_attr "cc" "clobber")])
;; Tests of bit 7 are pessimized to sign tests, so we need this too...
@@ -4017,11 +3914,11 @@
}
[(set (attr "length")
(if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
- (le (minus (pc) (match_dup 2)) (const_int 2046)))
- (const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 2)
- (const_int 4))))
+ (le (minus (pc) (match_dup 2)) (const_int 2046)))
+ (const_int 2)
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 2)
+ (const_int 4))))
(set_attr "cc" "clobber")])
;; Upper half of the I/O space - read port to __tmp_reg__ and use sbrc/sbrs.
@@ -4040,11 +3937,11 @@
"* return avr_out_sbxx_branch (insn, operands);"
[(set (attr "length")
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
- (le (minus (pc) (match_dup 3)) (const_int 2045)))
- (const_int 3)
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 3)
- (const_int 5))))
+ (le (minus (pc) (match_dup 3)) (const_int 2045)))
+ (const_int 3)
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 3)
+ (const_int 5))))
(set_attr "cc" "clobber")])
(define_insn "*sbix_branch_tmp_bit7"
@@ -4065,7 +3962,7 @@
(if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
(le (minus (pc) (match_dup 2)) (const_int 2045)))
(const_int 3)
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 3)
(const_int 5))))
(set_attr "cc" "clobber")])
@@ -4228,10 +4125,10 @@
;; Library prologue saves
(define_insn "call_prologue_saves"
[(unspec_volatile:HI [(const_int 0)] UNSPECV_PROLOGUE_SAVES)
- (match_operand:HI 0 "immediate_operand" "")
- (set (reg:HI REG_SP) (minus:HI
- (reg:HI REG_SP)
- (match_operand:HI 1 "immediate_operand" "")))
+ (match_operand:HI 0 "immediate_operand" "i,i")
+ (set (reg:HI REG_SP)
+ (minus:HI (reg:HI REG_SP)
+ (match_operand:HI 1 "immediate_operand" "i,i")))
(use (reg:HI REG_X))
(clobber (reg:HI REG_Z))]
""
@@ -4239,30 +4136,26 @@
ldi r31,hi8(gs(1f))
%~jmp __prologue_saves__+((18 - %0) * 2)
1:"
- [(set_attr_alternative "length"
- [(if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 6)
- (const_int 5))])
- (set_attr "cc" "clobber")
- ])
+ [(set_attr "length" "5,6")
+ (set_attr "cc" "clobber")
+ (set_attr "isa" "rjmp,jmp")])
; epilogue restores using library
(define_insn "epilogue_restores"
[(unspec_volatile:QI [(const_int 0)] UNSPECV_EPILOGUE_RESTORES)
- (set (reg:HI REG_Y ) (plus:HI
- (reg:HI REG_Y)
- (match_operand:HI 0 "immediate_operand" "")))
- (set (reg:HI REG_SP) (reg:HI REG_Y))
- (clobber (reg:QI REG_Z))]
+ (set (reg:HI REG_Y)
+ (plus:HI (reg:HI REG_Y)
+ (match_operand:HI 0 "immediate_operand" "i,i")))
+ (set (reg:HI REG_SP)
+ (plus:HI (reg:HI REG_Y)
+ (match_dup 0)))
+ (clobber (reg:QI REG_Z))]
""
"ldi r30, lo8(%0)
%~jmp __epilogue_restores__ + ((18 - %0) * 2)"
- [(set_attr_alternative "length"
- [(if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 3)
- (const_int 2))])
- (set_attr "cc" "clobber")
- ])
+ [(set_attr "length" "2,3")
+ (set_attr "cc" "clobber")
+ (set_attr "isa" "rjmp,jmp")])
; return
(define_insn "return"
@@ -4304,11 +4197,10 @@
(define_expand "prologue"
[(const_int 0)]
""
- "
{
expand_prologue ();
DONE;
- }")
+ })
(define_expand "epilogue"
[(const_int 0)]
diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index 1128dd3bf02..277b6007ee0 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -61,3 +61,7 @@ Relax branches
mpmem-wrap-around
Target Report
Make the linker relaxation machine assume that a program counter wrap-around occurs.
+
+mstrict-X
+Target Report Var(avr_strict_X) Init(0)
+When accessing RAM, use X as imposed by the hardware, i.e. just use pre-decrement, post-increment and indirect addressing with the X register. Without this option, the compiler may assume that there is an addressing mode X+const similar to Y+const and Z+const and emit instructions to emulate such an addressing mode for X.
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
index a4e4b4215b5..8df36072370 100644
--- a/gcc/config/avr/libgcc.S
+++ b/gcc/config/avr/libgcc.S
@@ -821,27 +821,31 @@ ENDF __tablejump2__
DEFUN __tablejump__
#if defined (__AVR_HAVE_LPMX__)
- lpm __tmp_reg__, Z+
- lpm r31, Z
- mov r30, __tmp_reg__
-
#if defined (__AVR_HAVE_EIJMP_EICALL__)
- eijmp
-#else
+ lpm __tmp_reg__, Z+
+ push __tmp_reg__
+ lpm __tmp_reg__, Z
+ push __tmp_reg__
+ push __zero_reg__
+ ret
+#else
+ lpm __tmp_reg__, Z+
+ lpm r31, Z
+ mov r30, __tmp_reg__
ijmp
#endif
-#else
+#else /* !HAVE_LPMX */
lpm
- adiw r30, 1
- push r0
+ adiw r30, 1
+ push r0
lpm
- push r0
+ push r0
#if defined (__AVR_HAVE_EIJMP_EICALL__)
- push __zero_reg__
+ push __zero_reg__
#endif
ret
-#endif
+#endif /* !HAVE_LPMX */
ENDF __tablejump__
#endif /* defined (L_tablejump) */
diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
index ba91de1d81f..f37927e1971 100644
--- a/gcc/config/cris/cris-protos.h
+++ b/gcc/config/cris/cris-protos.h
@@ -38,7 +38,6 @@ extern bool cris_valid_pic_const (rtx, bool);
extern bool cris_store_multiple_op_p (rtx);
extern bool cris_movem_load_rest_p (rtx, int);
extern void cris_asm_output_symbol_ref (FILE *, rtx);
-extern bool cris_output_addr_const_extra (FILE *, rtx);
extern int cris_cfun_uses_pic_table (void);
extern void cris_asm_output_case_end (FILE *, int, rtx);
extern rtx cris_gen_movem_load (rtx, rtx, int);
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 24cfa5a2d53..35ecaa8e2fd 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -113,6 +113,8 @@ static void cris_print_operand_address (FILE *, rtx);
static bool cris_print_operand_punct_valid_p (unsigned char code);
+static bool cris_output_addr_const_extra (FILE *, rtx);
+
static void cris_conditional_register_usage (void);
static void cris_asm_output_mi_thunk
@@ -121,6 +123,8 @@ static void cris_asm_output_mi_thunk
static void cris_file_start (void);
static void cris_init_libfuncs (void);
+static reg_class_t cris_preferred_reload_class (rtx, reg_class_t);
+
static int cris_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
static int cris_memory_move_cost (enum machine_mode, reg_class_t, bool);
static bool cris_rtx_costs (rtx, int, int, int, int *, bool);
@@ -179,6 +183,8 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
#define TARGET_PRINT_OPERAND_ADDRESS cris_print_operand_address
#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
#define TARGET_PRINT_OPERAND_PUNCT_VALID_P cris_print_operand_punct_valid_p
+#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
+#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA cris_output_addr_const_extra
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE cris_conditional_register_usage
@@ -194,6 +200,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS cris_init_libfuncs
+#undef TARGET_PREFERRED_RELOAD_CLASS
+#define TARGET_PREFERRED_RELOAD_CLASS cris_preferred_reload_class
+
#undef TARGET_REGISTER_MOVE_COST
#define TARGET_REGISTER_MOVE_COST cris_register_move_cost
#undef TARGET_MEMORY_MOVE_COST
@@ -1338,6 +1347,31 @@ cris_reload_address_legitimized (rtx x,
return false;
}
+
+/* Worker function for TARGET_PREFERRED_RELOAD_CLASS.
+
+ It seems like gcc (2.7.2 and 2.9x of 2000-03-22) may send "NO_REGS" as
+ the class for a constant (testcase: __Mul in arit.c). To avoid forcing
+ out a constant into the constant pool, we will trap this case and
+ return something a bit more sane. FIXME: Check if this is a bug.
+ Beware that we must not "override" classes that can be specified as
+ constraint letters, or else asm operands using them will fail when
+ they need to be reloaded. FIXME: Investigate whether that constitutes
+ a bug. */
+
+static reg_class_t
+cris_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass)
+{
+ if (rclass != ACR_REGS
+ && rclass != MOF_REGS
+ && rclass != SRP_REGS
+ && rclass != CC0_REGS
+ && rclass != SPECIAL_REGS)
+ return GENERAL_REGS;
+
+ return rclass;
+}
+
/* Worker function for TARGET_REGISTER_MOVE_COST. */
static int
@@ -3608,9 +3642,9 @@ cris_asm_output_label_ref (FILE *file, char *buf)
assemble_name (file, buf);
}
-/* Worker function for OUTPUT_ADDR_CONST_EXTRA. */
+/* Worker function for TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
-bool
+static bool
cris_output_addr_const_extra (FILE *file, rtx xconst)
{
switch (GET_CODE (xconst))
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index 872165ed796..4c28e4530ab 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -583,22 +583,6 @@ enum reg_class
/* See REGNO_OK_FOR_BASE_P. */
#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
-/* It seems like gcc (2.7.2 and 2.9x of 2000-03-22) may send "NO_REGS" as
- the class for a constant (testcase: __Mul in arit.c). To avoid forcing
- out a constant into the constant pool, we will trap this case and
- return something a bit more sane. FIXME: Check if this is a bug.
- Beware that we must not "override" classes that can be specified as
- constraint letters, or else asm operands using them will fail when
- they need to be reloaded. FIXME: Investigate whether that constitutes
- a bug. */
-#define PREFERRED_RELOAD_CLASS(X, CLASS) \
- ((CLASS) != ACR_REGS \
- && (CLASS) != MOF_REGS \
- && (CLASS) != SRP_REGS \
- && (CLASS) != CC0_REGS \
- && (CLASS) != SPECIAL_REGS \
- ? GENERAL_REGS : (CLASS))
-
/* We can't move special registers to and from memory in smaller than
word_mode. We also can't move between special registers. Luckily,
-1, as returned by true_regnum for non-sub/registers, is valid as a
@@ -1097,9 +1081,6 @@ enum cris_pic_symbol_type
/* Node: Data Output */
-#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
- do { if (!cris_output_addr_const_extra (STREAM, X)) goto FAIL; } while (0)
-
#define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) (C) == '@'
/* Node: Uninitialized Data */
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index bedda1ec65b..e8e18b83adb 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -2957,12 +2957,13 @@ darwin_override_options (void)
darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
}
-/* Add $LDBL128 suffix to long double builtins. */
+#if DARWIN_PPC
+/* Add $LDBL128 suffix to long double builtins for ppc darwin. */
static void
-darwin_patch_builtin (int fncode)
+darwin_patch_builtin (enum built_in_function fncode)
{
- tree fn = built_in_decls[fncode];
+ tree fn = builtin_decl_explicit (fncode);
tree sym;
char *newname;
@@ -2974,7 +2975,7 @@ darwin_patch_builtin (int fncode)
set_user_assembler_name (fn, newname);
- fn = implicit_built_in_decls[fncode];
+ fn = builtin_decl_implicit (fncode);
if (fn)
set_user_assembler_name (fn, newname);
}
@@ -2998,6 +2999,7 @@ darwin_patch_builtins (void)
#undef PATCH_BUILTIN_NO64
#undef PATCH_BUILTIN_VARIADIC
}
+#endif
/* CFStrings implementation. */
static GTY(()) tree cfstring_class_reference = NULL_TREE;
@@ -3149,9 +3151,10 @@ darwin_rename_builtins (void)
use the faster version. */
if (!flag_unsafe_math_optimizations)
{
- int dcode = (BUILT_IN_COMPLEX_DIV_MIN
- + DCmode - MIN_MODE_COMPLEX_FLOAT);
- tree fn = built_in_decls[dcode];
+ enum built_in_function dcode
+ = (enum built_in_function)(BUILT_IN_COMPLEX_DIV_MIN
+ + DCmode - MIN_MODE_COMPLEX_FLOAT);
+ tree fn = builtin_decl_explicit (dcode);
/* Fortran and c call TARGET_INIT_BUILTINS and
TARGET_INIT_LIBFUNCS at different times, so we have to put a
call into each to ensure that at least one of them is called
@@ -3159,7 +3162,7 @@ darwin_rename_builtins (void)
new hook to run after build_common_builtin_nodes runs. */
if (fn)
set_user_assembler_name (fn, "___ieee_divdc3");
- fn = implicit_built_in_decls[dcode];
+ fn = builtin_decl_implicit (dcode);
if (fn)
set_user_assembler_name (fn, "___ieee_divdc3");
}
diff --git a/gcc/config/gnu.h b/gcc/config/gnu.h
index 8b1d079ee89..dddbcbf5a49 100644
--- a/gcc/config/gnu.h
+++ b/gcc/config/gnu.h
@@ -28,10 +28,6 @@ along with GCC. If not, see <http://www.gnu.org/licenses/>.
#undef LIB_SPEC
#define LIB_SPEC "%{pthread:-lpthread} %{pg|p|profile:-lc_p;:-lc}"
-/* Standard include directory. In GNU, "/usr" is a four-letter word. */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/include"
-
#undef GNU_USER_TARGET_OS_CPP_BUILTINS
#define GNU_USER_TARGET_OS_CPP_BUILTINS() \
do { \
diff --git a/gcc/config/i386/djgpp.h b/gcc/config/i386/djgpp.h
index d1109a2ff3f..c770219657c 100644
--- a/gcc/config/i386/djgpp.h
+++ b/gcc/config/i386/djgpp.h
@@ -48,10 +48,6 @@ along with GCC; see the file COPYING3. If not see
/* We override default /usr or /usr/local part with /dev/env/DJDIR which */
/* points to actual DJGPP installation directory. */
-/* Standard include directory */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/dev/env/DJDIR/include/"
-
/* Search for as.exe and ld.exe in DJGPP's binary directory. */
#undef MD_EXEC_PREFIX
#define MD_EXEC_PREFIX "/dev/env/DJDIR/bin/"
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 707f217ab61..bdac6ff0666 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -123,6 +123,8 @@ extern bool ix86_expand_int_movcc (rtx[]);
extern bool ix86_expand_fp_movcc (rtx[]);
extern bool ix86_expand_fp_vcond (rtx[]);
extern bool ix86_expand_int_vcond (rtx[]);
+extern void ix86_expand_vec_perm (rtx[]);
+extern bool ix86_expand_vec_perm_const (rtx[]);
extern void ix86_expand_sse_unpack (rtx[], bool, bool);
extern bool ix86_expand_int_addcc (rtx[]);
extern rtx ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 7e89dbde7b9..4af4e5958b7 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1672,7 +1672,7 @@ struct processor_costs atom_cost = {
COSTS_N_INSNS (1), /* cost of movzx */
8, /* "large" insn */
17, /* MOVE_RATIO */
- 2, /* cost for loading QImode using movzbl */
+ 4, /* cost for loading QImode using movzbl */
{4, 4, 4}, /* cost of loading integer registers
in QImode, HImode and SImode.
Relative to reg-reg move (2). */
@@ -3057,6 +3057,22 @@ ix86_option_override_internal (bool main_args_p)
PTA_64BIT /* flags are only used for -march switch. */ },
};
+ /* -mrecip options. */
+ static struct
+ {
+ const char *string; /* option name */
+ unsigned int mask; /* mask bits to set */
+ }
+ const recip_options[] =
+ {
+ { "all", RECIP_MASK_ALL },
+ { "none", RECIP_MASK_NONE },
+ { "div", RECIP_MASK_DIV },
+ { "sqrt", RECIP_MASK_SQRT },
+ { "vec-div", RECIP_MASK_VEC_DIV },
+ { "vec-sqrt", RECIP_MASK_VEC_SQRT },
+ };
+
int const pta_size = ARRAY_SIZE (processor_alias_table);
/* Set up prefix/suffix so the error messages refer to either the command
@@ -3814,6 +3830,56 @@ ix86_option_override_internal (bool main_args_p)
target_flags &= ~MASK_VZEROUPPER;
}
+ if (ix86_recip_name)
+ {
+ char *p = ASTRDUP (ix86_recip_name);
+ char *q;
+ unsigned int mask, i;
+ bool invert;
+
+ while ((q = strtok (p, ",")) != NULL)
+ {
+ p = NULL;
+ if (*q == '!')
+ {
+ invert = true;
+ q++;
+ }
+ else
+ invert = false;
+
+ if (!strcmp (q, "default"))
+ mask = RECIP_MASK_ALL;
+ else
+ {
+ for (i = 0; i < ARRAY_SIZE (recip_options); i++)
+ if (!strcmp (q, recip_options[i].string))
+ {
+ mask = recip_options[i].mask;
+ break;
+ }
+
+ if (i == ARRAY_SIZE (recip_options))
+ {
+ error ("unknown option for -mrecip=%s", q);
+ invert = false;
+ mask = RECIP_MASK_NONE;
+ }
+ }
+
+ recip_mask_explicit |= mask;
+ if (invert)
+ recip_mask &= ~mask;
+ else
+ recip_mask |= mask;
+ }
+ }
+
+ if (TARGET_RECIP)
+ recip_mask |= RECIP_MASK_ALL & ~recip_mask_explicit;
+ else if (target_flags_explicit & MASK_RECIP)
+ recip_mask &= ~(RECIP_MASK_ALL & ~recip_mask_explicit);
+
/* Save the initial options in case the user does function specific
options. */
if (main_args_p)
@@ -3946,6 +4012,7 @@ ix86_function_specific_save (struct cl_target_option *ptr)
ptr->arch_specified = ix86_arch_specified;
ptr->x_ix86_isa_flags_explicit = ix86_isa_flags_explicit;
ptr->ix86_target_flags_explicit = target_flags_explicit;
+ ptr->x_recip_mask_explicit = recip_mask_explicit;
/* The fields are char but the variables are not; make sure the
values fit in the fields. */
@@ -3973,6 +4040,7 @@ ix86_function_specific_restore (struct cl_target_option *ptr)
ix86_arch_specified = ptr->arch_specified;
ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit;
target_flags_explicit = ptr->ix86_target_flags_explicit;
+ recip_mask_explicit = ptr->x_recip_mask_explicit;
/* Recreate the arch feature tests if the arch changed */
if (old_arch != ix86_arch)
@@ -7959,7 +8027,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
else
{
tree copy
- = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
3, dest_addr, src_addr,
size_int (cur_size));
gimplify_and_add (copy, pre_p);
@@ -9134,7 +9202,8 @@ static GTY(()) rtx queued_cfa_restores;
static void
ix86_add_cfa_restore_note (rtx insn, rtx reg, HOST_WIDE_INT cfa_offset)
{
- if (cfa_offset <= cfun->machine->fs.red_zone_offset)
+ if (!crtl->shrink_wrapped
+ && cfa_offset <= cfun->machine->fs.red_zone_offset)
return;
if (insn)
@@ -10738,6 +10807,8 @@ ix86_expand_epilogue (int style)
GEN_INT (m->fs.sp_offset - UNITS_PER_WORD),
style, true);
}
+ else
+ ix86_add_queued_cfa_restore_notes (get_last_insn ());
/* Sibcall epilogues don't want a return instruction. */
if (style == 0)
@@ -10779,13 +10850,13 @@ ix86_expand_epilogue (int style)
pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
popc, -1, true);
- emit_jump_insn (gen_return_indirect_internal (ecx));
+ emit_jump_insn (gen_simple_return_indirect_internal (ecx));
}
else
- emit_jump_insn (gen_return_pop_internal (popc));
+ emit_jump_insn (gen_simple_return_pop_internal (popc));
}
else
- emit_jump_insn (gen_return_internal ());
+ emit_jump_insn (gen_simple_return_internal ());
/* Restore the state back to the state from the prologue,
so that it's correct for the next epilogue. */
@@ -15727,6 +15798,12 @@ ix86_fixup_binary_operands (enum rtx_code code, enum machine_mode mode,
if (MEM_P (src1) && !rtx_equal_p (dst, src1))
src1 = force_reg (mode, src1);
+ /* Improve address combine. */
+ if (code == PLUS
+ && GET_MODE_CLASS (mode) == MODE_INT
+ && MEM_P (src2))
+ src2 = force_reg (mode, src2);
+
operands[1] = src1;
operands[2] = src2;
return dst;
@@ -16139,19 +16216,20 @@ distance_non_agu_define (unsigned int regno1, unsigned int regno2,
FOR_EACH_EDGE (e, ei, bb->preds)
{
- int bb_dist = distance_non_agu_define_in_bb (regno1, regno2,
- insn, distance,
- BB_END (e->src),
- &found_in_bb);
+ int bb_dist
+ = distance_non_agu_define_in_bb (regno1, regno2,
+ insn, distance,
+ BB_END (e->src),
+ &found_in_bb);
if (found_in_bb)
{
if (shortest_dist < 0)
shortest_dist = bb_dist;
else if (bb_dist > 0)
shortest_dist = MIN (bb_dist, shortest_dist);
- }
- found = found || found_in_bb;
+ found = true;
+ }
}
distance = shortest_dist;
@@ -16164,11 +16242,9 @@ distance_non_agu_define (unsigned int regno1, unsigned int regno2,
extract_insn_cached (insn);
if (!found)
- distance = -1;
- else
- distance = distance >> 1;
+ return -1;
- return distance;
+ return distance >> 1;
}
/* Return the distance in half-cycles between INSN and the next
@@ -16181,9 +16257,9 @@ distance_non_agu_define (unsigned int regno1, unsigned int regno2,
found and false otherwise. */
static int
-distance_agu_use_in_bb(unsigned int regno,
- rtx insn, int distance, rtx start,
- bool *found, bool *redefined)
+distance_agu_use_in_bb (unsigned int regno,
+ rtx insn, int distance, rtx start,
+ bool *found, bool *redefined)
{
basic_block bb = start ? BLOCK_FOR_INSN (start) : NULL;
rtx next = start;
@@ -16268,18 +16344,19 @@ distance_agu_use (unsigned int regno0, rtx insn)
FOR_EACH_EDGE (e, ei, bb->succs)
{
- int bb_dist = distance_agu_use_in_bb (regno0, insn,
- distance, BB_HEAD (e->dest),
- &found_in_bb, &redefined_in_bb);
+ int bb_dist
+ = distance_agu_use_in_bb (regno0, insn,
+ distance, BB_HEAD (e->dest),
+ &found_in_bb, &redefined_in_bb);
if (found_in_bb)
{
if (shortest_dist < 0)
shortest_dist = bb_dist;
else if (bb_dist > 0)
shortest_dist = MIN (bb_dist, shortest_dist);
- }
- found = found || found_in_bb;
+ found = true;
+ }
}
distance = shortest_dist;
@@ -16287,11 +16364,9 @@ distance_agu_use (unsigned int regno0, rtx insn)
}
if (!found || redefined)
- distance = -1;
- else
- distance = distance >> 1;
+ return -1;
- return distance;
+ return distance >> 1;
}
/* Define this macro to tune LEA priority vs ADD, it take effect when
@@ -16346,7 +16421,7 @@ ix86_lea_outperforms (rtx insn, unsigned int regno0, unsigned int regno1,
false otherwise. */
static bool
-ix86_ok_to_clobber_flags(rtx insn)
+ix86_ok_to_clobber_flags (rtx insn)
{
basic_block bb = BLOCK_FOR_INSN (insn);
df_ref *use;
@@ -16470,6 +16545,21 @@ ix86_avoid_lea_for_addr (rtx insn, rtx operands[])
return !ix86_lea_outperforms (insn, regno0, regno1, regno2, split_cost);
}
+/* Emit x86 binary operand CODE in mode MODE, where the first operand
+ matches destination. RTX includes clobber of FLAGS_REG. */
+
+static void
+ix86_emit_binop (enum rtx_code code, enum machine_mode mode,
+ rtx dst, rtx src)
+{
+ rtx op, clob;
+
+ op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_ee (code, mode, dst, src));
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
+}
+
/* Split lea instructions into a sequence of instructions
which are executed on ALU to avoid AGU stalls.
It is assumed that it is allowed to clobber flags register
@@ -16482,8 +16572,7 @@ ix86_split_lea_for_addr (rtx operands[], enum machine_mode mode)
unsigned int regno1 = INVALID_REGNUM;
unsigned int regno2 = INVALID_REGNUM;
struct ix86_address parts;
- rtx tmp, clob;
- rtvec par;
+ rtx tmp;
int ok, adds;
ok = ix86_decompose_address (operands[1], &parts);
@@ -16515,14 +16604,7 @@ ix86_split_lea_for_addr (rtx operands[], enum machine_mode mode)
gcc_assert (regno2 != regno0);
for (adds = parts.scale; adds > 0; adds--)
- {
- tmp = gen_rtx_PLUS (mode, operands[0], parts.index);
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- clob = gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (CCmode, FLAGS_REG));
- par = gen_rtvec (2, tmp, clob);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
- }
+ ix86_emit_binop (PLUS, mode, operands[0], parts.index);
}
else
{
@@ -16531,30 +16613,14 @@ ix86_split_lea_for_addr (rtx operands[], enum machine_mode mode)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], parts.index));
/* Use shift for scaling. */
- tmp = gen_rtx_ASHIFT (mode, operands[0],
- GEN_INT (exact_log2 (parts.scale)));
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- par = gen_rtvec (2, tmp, clob);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
+ ix86_emit_binop (ASHIFT, mode, operands[0],
+ GEN_INT (exact_log2 (parts.scale)));
if (parts.base)
- {
- tmp = gen_rtx_PLUS (mode, operands[0], parts.base);
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- par = gen_rtvec (2, tmp, clob);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
- }
+ ix86_emit_binop (PLUS, mode, operands[0], parts.base);
if (parts.disp && parts.disp != const0_rtx)
- {
- tmp = gen_rtx_PLUS (mode, operands[0], parts.disp);
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- par = gen_rtvec (2, tmp, clob);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
- }
+ ix86_emit_binop (PLUS, mode, operands[0], parts.disp);
}
}
else if (!parts.base && !parts.index)
@@ -16565,41 +16631,32 @@ ix86_split_lea_for_addr (rtx operands[], enum machine_mode mode)
else
{
if (!parts.base)
- {
- if (regno0 != regno2)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], parts.index));
- }
+ {
+ if (regno0 != regno2)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], parts.index));
+ }
else if (!parts.index)
- {
- if (regno0 != regno1)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], parts.base));
- }
- else
- {
- if (regno0 == regno1)
- tmp = gen_rtx_PLUS (mode, operands[0], parts.index);
- else if (regno0 == regno2)
- tmp = gen_rtx_PLUS (mode, operands[0], parts.base);
- else
- {
+ {
+ if (regno0 != regno1)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], parts.base));
- tmp = gen_rtx_PLUS (mode, operands[0], parts.index);
- }
+ }
+ else
+ {
+ if (regno0 == regno1)
+ tmp = parts.index;
+ else if (regno0 == regno2)
+ tmp = parts.base;
+ else
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], parts.base));
+ tmp = parts.index;
+ }
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- par = gen_rtvec (2, tmp, clob);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
- }
+ ix86_emit_binop (PLUS, mode, operands[0], tmp);
+ }
if (parts.disp && parts.disp != const0_rtx)
- {
- tmp = gen_rtx_PLUS (mode, operands[0], parts.disp);
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- par = gen_rtvec (2, tmp, clob);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
- }
+ ix86_emit_binop (PLUS, mode, operands[0], parts.disp);
}
}
@@ -16951,6 +17008,10 @@ ix86_build_const_vector (enum machine_mode mode, bool vect, rtx value)
switch (mode)
{
+ case V32QImode:
+ case V16QImode:
+ case V16HImode:
+ case V8HImode:
case V8SImode:
case V4SImode:
case V4DImode:
@@ -18890,7 +18951,7 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
enum machine_mode mode = GET_MODE (dest);
rtx t2, t3, x;
- if (vector_all_ones_operand (op_true, GET_MODE (op_true))
+ if (vector_all_ones_operand (op_true, mode)
&& rtx_equal_p (op_false, CONST0_RTX (mode)))
{
emit_insn (gen_rtx_SET (VOIDmode, dest, cmp));
@@ -19119,7 +19180,8 @@ ix86_expand_fp_vcond (rtx operands[])
bool
ix86_expand_int_vcond (rtx operands[])
{
- enum machine_mode mode = GET_MODE (operands[0]);
+ enum machine_mode data_mode = GET_MODE (operands[0]);
+ enum machine_mode mode = GET_MODE (operands[4]);
enum rtx_code code = GET_CODE (operands[3]);
bool negate = false;
rtx x, cop0, cop1;
@@ -19246,14 +19308,372 @@ ix86_expand_int_vcond (rtx operands[])
}
}
- x = ix86_expand_sse_cmp (operands[0], code, cop0, cop1,
- operands[1+negate], operands[2-negate]);
+ /* Allow the comparison to be done in one mode, but the movcc to
+ happen in another mode. */
+ if (data_mode == mode)
+ {
+ x = ix86_expand_sse_cmp (operands[0], code, cop0, cop1,
+ operands[1+negate], operands[2-negate]);
+ }
+ else
+ {
+ gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
+ x = ix86_expand_sse_cmp (gen_lowpart (mode, operands[0]),
+ code, cop0, cop1,
+ operands[1+negate], operands[2-negate]);
+ x = gen_lowpart (data_mode, x);
+ }
ix86_expand_sse_movcc (operands[0], x, operands[1+negate],
operands[2-negate]);
return true;
}
+/* Expand a variable vector permutation. */
+
+void
+ix86_expand_vec_perm (rtx operands[])
+{
+ rtx target = operands[0];
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx mask = operands[3];
+ rtx t1, t2, t3, t4, vt, vt2, vec[32];
+ enum machine_mode mode = GET_MODE (op0);
+ enum machine_mode maskmode = GET_MODE (mask);
+ int w, e, i;
+ bool one_operand_shuffle = rtx_equal_p (op0, op1);
+
+ /* Number of elements in the vector. */
+ w = GET_MODE_NUNITS (mode);
+ e = GET_MODE_UNIT_SIZE (mode);
+ gcc_assert (w <= 32);
+
+ if (TARGET_AVX2)
+ {
+ if (mode == V4DImode || mode == V4DFmode || mode == V16HImode)
+ {
+ /* Unfortunately, the VPERMQ and VPERMPD instructions only support
+ an constant shuffle operand. With a tiny bit of effort we can
+ use VPERMD instead. A re-interpretation stall for V4DFmode is
+ unfortunate but there's no avoiding it.
+ Similarly for V16HImode we don't have instructions for variable
+ shuffling, while for V32QImode we can use after preparing suitable
+ masks vpshufb; vpshufb; vpermq; vpor. */
+
+ if (mode == V16HImode)
+ {
+ maskmode = mode = V32QImode;
+ w = 32;
+ e = 1;
+ }
+ else
+ {
+ maskmode = mode = V8SImode;
+ w = 8;
+ e = 4;
+ }
+ t1 = gen_reg_rtx (maskmode);
+
+ /* Replicate the low bits of the V4DImode mask into V8SImode:
+ mask = { A B C D }
+ t1 = { A A B B C C D D }. */
+ for (i = 0; i < w / 2; ++i)
+ vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
+ vt = force_reg (maskmode, vt);
+ mask = gen_lowpart (maskmode, mask);
+ if (maskmode == V8SImode)
+ emit_insn (gen_avx2_permvarv8si (t1, vt, mask));
+ else
+ emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt));
+
+ /* Multiply the shuffle indicies by two. */
+ t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
+ OPTAB_DIRECT);
+
+ /* Add one to the odd shuffle indicies:
+ t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */
+ for (i = 0; i < w / 2; ++i)
+ {
+ vec[i * 2] = const0_rtx;
+ vec[i * 2 + 1] = const1_rtx;
+ }
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
+ vt = force_const_mem (maskmode, vt);
+ t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
+ OPTAB_DIRECT);
+
+ /* Continue as if V8SImode (resp. V32QImode) was used initially. */
+ operands[3] = mask = t1;
+ target = gen_lowpart (mode, target);
+ op0 = gen_lowpart (mode, op0);
+ op1 = gen_lowpart (mode, op1);
+ }
+
+ switch (mode)
+ {
+ case V8SImode:
+ /* The VPERMD and VPERMPS instructions already properly ignore
+ the high bits of the shuffle elements. No need for us to
+ perform an AND ourselves. */
+ if (one_operand_shuffle)
+ emit_insn (gen_avx2_permvarv8si (target, mask, op0));
+ else
+ {
+ t1 = gen_reg_rtx (V8SImode);
+ t2 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx2_permvarv8si (t1, mask, op0));
+ emit_insn (gen_avx2_permvarv8si (t2, mask, op1));
+ goto merge_two;
+ }
+ return;
+
+ case V8SFmode:
+ mask = gen_lowpart (V8SFmode, mask);
+ if (one_operand_shuffle)
+ emit_insn (gen_avx2_permvarv8sf (target, mask, op0));
+ else
+ {
+ t1 = gen_reg_rtx (V8SFmode);
+ t2 = gen_reg_rtx (V8SFmode);
+ emit_insn (gen_avx2_permvarv8sf (t1, mask, op0));
+ emit_insn (gen_avx2_permvarv8sf (t2, mask, op1));
+ goto merge_two;
+ }
+ return;
+
+ case V4SImode:
+ /* By combining the two 128-bit input vectors into one 256-bit
+ input vector, we can use VPERMD and VPERMPS for the full
+ two-operand shuffle. */
+ t1 = gen_reg_rtx (V8SImode);
+ t2 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx_vec_concatv8si (t1, op0, op1));
+ emit_insn (gen_avx_vec_concatv8si (t2, mask, mask));
+ emit_insn (gen_avx2_permvarv8si (t1, t2, t1));
+ emit_insn (gen_avx_vextractf128v8si (target, t1, const0_rtx));
+ return;
+
+ case V4SFmode:
+ t1 = gen_reg_rtx (V8SFmode);
+ t2 = gen_reg_rtx (V8SFmode);
+ mask = gen_lowpart (V4SFmode, mask);
+ emit_insn (gen_avx_vec_concatv8sf (t1, op0, op1));
+ emit_insn (gen_avx_vec_concatv8sf (t2, mask, mask));
+ emit_insn (gen_avx2_permvarv8sf (t1, t2, t1));
+ emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx));
+ return;
+
+ case V32QImode:
+ t1 = gen_reg_rtx (V32QImode);
+ t2 = gen_reg_rtx (V32QImode);
+ t3 = gen_reg_rtx (V32QImode);
+ vt2 = GEN_INT (128);
+ for (i = 0; i < 32; i++)
+ vec[i] = vt2;
+ vt = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
+ vt = force_reg (V32QImode, vt);
+ for (i = 0; i < 32; i++)
+ vec[i] = i < 16 ? vt2 : const0_rtx;
+ vt2 = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
+ vt2 = force_reg (V32QImode, vt2);
+ /* From mask create two adjusted masks, which contain the same
+ bits as mask in the low 7 bits of each vector element.
+ The first mask will have the most significant bit clear
+ if it requests element from the same 128-bit lane
+ and MSB set if it requests element from the other 128-bit lane.
+ The second mask will have the opposite values of the MSB,
+ and additionally will have its 128-bit lanes swapped.
+ E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have
+ t1 { 07 92 9e 09 ... | 17 19 85 1f ... } and
+ t3 { 97 99 05 9f ... | 87 12 1e 89 ... } where each ...
+ stands for other 12 bytes. */
+ /* The bit whether element is from the same lane or the other
+ lane is bit 4, so shift it up by 3 to the MSB position. */
+ emit_insn (gen_avx2_lshlv4di3 (gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, mask),
+ GEN_INT (3)));
+ /* Clear MSB bits from the mask just in case it had them set. */
+ emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
+ /* After this t1 will have MSB set for elements from other lane. */
+ emit_insn (gen_xorv32qi3 (t1, t1, vt2));
+ /* Clear bits other than MSB. */
+ emit_insn (gen_andv32qi3 (t1, t1, vt));
+ /* Or in the lower bits from mask into t3. */
+ emit_insn (gen_iorv32qi3 (t3, t1, t2));
+ /* And invert MSB bits in t1, so MSB is set for elements from the same
+ lane. */
+ emit_insn (gen_xorv32qi3 (t1, t1, vt));
+ /* Swap 128-bit lanes in t3. */
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
+ gen_lowpart (V4DImode, t3),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ /* And or in the lower bits from mask into t1. */
+ emit_insn (gen_iorv32qi3 (t1, t1, t2));
+ if (one_operand_shuffle)
+ {
+ /* Each of these shuffles will put 0s in places where
+ element from the other 128-bit lane is needed, otherwise
+ will shuffle in the requested value. */
+ emit_insn (gen_avx2_pshufbv32qi3 (t3, op0, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
+ /* For t3 the 128-bit lanes are swapped again. */
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
+ gen_lowpart (V4DImode, t3),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ /* And oring both together leads to the result. */
+ emit_insn (gen_iorv32qi3 (target, t1, t3));
+ return;
+ }
+
+ t4 = gen_reg_rtx (V32QImode);
+ /* Similarly to the above one_operand_shuffle code,
+ just for repeated twice for each operand. merge_two:
+ code will merge the two results together. */
+ emit_insn (gen_avx2_pshufbv32qi3 (t4, op0, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t3, op1, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
+ emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t4),
+ gen_lowpart (V4DImode, t4),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
+ gen_lowpart (V4DImode, t3),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ emit_insn (gen_iorv32qi3 (t4, t2, t4));
+ emit_insn (gen_iorv32qi3 (t3, t1, t3));
+ t1 = t4;
+ t2 = t3;
+ goto merge_two;
+
+ default:
+ gcc_assert (GET_MODE_SIZE (mode) <= 16);
+ break;
+ }
+ }
+
+ if (TARGET_XOP)
+ {
+ /* The XOP VPPERM insn supports three inputs. By ignoring the
+ one_operand_shuffle special case, we avoid creating another
+ set of constant vectors in memory. */
+ one_operand_shuffle = false;
+
+ /* mask = mask & {2*w-1, ...} */
+ vt = GEN_INT (2*w - 1);
+ }
+ else
+ {
+ /* mask = mask & {w-1, ...} */
+ vt = GEN_INT (w - 1);
+ }
+
+ for (i = 0; i < w; i++)
+ vec[i] = vt;
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
+ mask = expand_simple_binop (maskmode, AND, mask, vt,
+ NULL_RTX, 0, OPTAB_DIRECT);
+
+ /* For non-QImode operations, convert the word permutation control
+ into a byte permutation control. */
+ if (mode != V16QImode)
+ {
+ mask = expand_simple_binop (maskmode, ASHIFT, mask,
+ GEN_INT (exact_log2 (e)),
+ NULL_RTX, 0, OPTAB_DIRECT);
+
+ /* Convert mask to vector of chars. */
+ mask = force_reg (V16QImode, gen_lowpart (V16QImode, mask));
+
+ /* Replicate each of the input bytes into byte positions:
+ (v2di) --> {0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8}
+ (v4si) --> {0,0,0,0, 4,4,4,4, 8,8,8,8, 12,12,12,12}
+ (v8hi) --> {0,0, 2,2, 4,4, 6,6, ...}. */
+ for (i = 0; i < 16; ++i)
+ vec[i] = GEN_INT (i/e * e);
+ vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
+ vt = force_const_mem (V16QImode, vt);
+ if (TARGET_XOP)
+ emit_insn (gen_xop_pperm (mask, mask, mask, vt));
+ else
+ emit_insn (gen_ssse3_pshufbv16qi3 (mask, mask, vt));
+
+ /* Convert it into the byte positions by doing
+ mask = mask + {0,1,..,16/w, 0,1,..,16/w, ...} */
+ for (i = 0; i < 16; ++i)
+ vec[i] = GEN_INT (i % e);
+ vt = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, vec));
+ vt = force_const_mem (V16QImode, vt);
+ emit_insn (gen_addv16qi3 (mask, mask, vt));
+ }
+
+ /* The actual shuffle operations all operate on V16QImode. */
+ op0 = gen_lowpart (V16QImode, op0);
+ op1 = gen_lowpart (V16QImode, op1);
+ target = gen_lowpart (V16QImode, target);
+
+ if (TARGET_XOP)
+ {
+ emit_insn (gen_xop_pperm (target, op0, op1, mask));
+ }
+ else if (one_operand_shuffle)
+ {
+ emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
+ }
+ else
+ {
+ rtx xops[6];
+ bool ok;
+
+ /* Shuffle the two input vectors independently. */
+ t1 = gen_reg_rtx (V16QImode);
+ t2 = gen_reg_rtx (V16QImode);
+ emit_insn (gen_ssse3_pshufbv16qi3 (t1, op0, mask));
+ emit_insn (gen_ssse3_pshufbv16qi3 (t2, op1, mask));
+
+ merge_two:
+ /* Then merge them together. The key is whether any given control
+ element contained a bit set that indicates the second word. */
+ mask = operands[3];
+ vt = GEN_INT (w);
+ if (maskmode == V2DImode && !TARGET_SSE4_1)
+ {
+ /* Without SSE4.1, we don't have V2DImode EQ. Perform one
+ more shuffle to convert the V2DI input mask into a V4SI
+ input mask. At which point the masking that expand_int_vcond
+ will work as desired. */
+ rtx t3 = gen_reg_rtx (V4SImode);
+ emit_insn (gen_sse2_pshufd_1 (t3, gen_lowpart (V4SImode, mask),
+ const0_rtx, const0_rtx,
+ const2_rtx, const2_rtx));
+ mask = t3;
+ maskmode = V4SImode;
+ e = w = 4;
+ }
+
+ for (i = 0; i < w; i++)
+ vec[i] = vt;
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
+ vt = force_reg (maskmode, vt);
+ mask = expand_simple_binop (maskmode, AND, mask, vt,
+ NULL_RTX, 0, OPTAB_DIRECT);
+
+ xops[0] = gen_lowpart (mode, operands[0]);
+ xops[1] = gen_lowpart (mode, t2);
+ xops[2] = gen_lowpart (mode, t1);
+ xops[3] = gen_rtx_EQ (maskmode, mask, vt);
+ xops[4] = mask;
+ xops[5] = vt;
+ ok = ix86_expand_int_vcond (xops);
+ gcc_assert (ok);
+ }
+}
+
/* Unpack OP[1] into the next wider integer vector type. UNSIGNED_P is
true if we should do zero extension, else sign extension. HIGH_P is
true if we want the N/2 high elements, else the low elements. */
@@ -19267,9 +19687,38 @@ ix86_expand_sse_unpack (rtx operands[2], bool unsigned_p, bool high_p)
if (TARGET_SSE4_1)
{
rtx (*unpack)(rtx, rtx);
+ rtx (*extract)(rtx, rtx) = NULL;
+ enum machine_mode halfmode = BLKmode;
switch (imode)
{
+ case V32QImode:
+ if (unsigned_p)
+ unpack = gen_avx2_zero_extendv16qiv16hi2;
+ else
+ unpack = gen_avx2_sign_extendv16qiv16hi2;
+ halfmode = V16QImode;
+ extract
+ = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi;
+ break;
+ case V16HImode:
+ if (unsigned_p)
+ unpack = gen_avx2_zero_extendv8hiv8si2;
+ else
+ unpack = gen_avx2_sign_extendv8hiv8si2;
+ halfmode = V8HImode;
+ extract
+ = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi;
+ break;
+ case V8SImode:
+ if (unsigned_p)
+ unpack = gen_avx2_zero_extendv4siv4di2;
+ else
+ unpack = gen_avx2_sign_extendv4siv4di2;
+ halfmode = V4SImode;
+ extract
+ = high_p ? gen_vec_extract_hi_v8si : gen_vec_extract_lo_v8si;
+ break;
case V16QImode:
if (unsigned_p)
unpack = gen_sse4_1_zero_extendv8qiv8hi2;
@@ -19292,7 +19741,12 @@ ix86_expand_sse_unpack (rtx operands[2], bool unsigned_p, bool high_p)
gcc_unreachable ();
}
- if (high_p)
+ if (GET_MODE_SIZE (imode) == 32)
+ {
+ tmp = gen_reg_rtx (halfmode);
+ emit_insn (extract (tmp, operands[1]));
+ }
+ else if (high_p)
{
/* Shift higher 8 bytes to lower 8 bytes. */
tmp = gen_reg_rtx (imode);
@@ -25797,7 +26251,7 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ssaddv16hi3, "__builtin_ia32_paddsw256", IX86_BUILTIN_PADDSW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_usaddv32qi3, "__builtin_ia32_paddusb256", IX86_BUILTIN_PADDUSB256, UNKNOWN, (int) V32QI_FTYPE_V32QI_V32QI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_usaddv16hi3, "__builtin_ia32_paddusw256", IX86_BUILTIN_PADDUSW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_palignrv4di, "__builtin_ia32_palignr256", IX86_BUILTIN_PALIGNR256, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_INT_CONVERT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_palignrv2ti, "__builtin_ia32_palignr256", IX86_BUILTIN_PALIGNR256, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_INT_CONVERT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_andv4di3, "__builtin_ia32_andsi256", IX86_BUILTIN_AND256I, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_andnotv4di3, "__builtin_ia32_andnotsi256", IX86_BUILTIN_ANDNOT256I, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_uavgv32qi3, "__builtin_ia32_pavgb256", IX86_BUILTIN_PAVGB256, UNKNOWN, (int) V32QI_FTYPE_V32QI_V32QI },
@@ -25861,7 +26315,7 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_psignv32qi3, "__builtin_ia32_psignb256", IX86_BUILTIN_PSIGNB256, UNKNOWN, (int) V32QI_FTYPE_V32QI_V32QI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_psignv16hi3, "__builtin_ia32_psignw256", IX86_BUILTIN_PSIGNW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_psignv8si3 , "__builtin_ia32_psignd256", IX86_BUILTIN_PSIGND256, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlqv4di3, "__builtin_ia32_pslldqi256", IX86_BUILTIN_PSLLDQI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_INT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashlv2ti3, "__builtin_ia32_pslldqi256", IX86_BUILTIN_PSLLDQI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_INT_CONVERT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv16hi3, "__builtin_ia32_psllwi256", IX86_BUILTIN_PSLLWI256 , UNKNOWN, (int) V16HI_FTYPE_V16HI_SI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv16hi3, "__builtin_ia32_psllw256", IX86_BUILTIN_PSLLW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V8HI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv8si3, "__builtin_ia32_pslldi256", IX86_BUILTIN_PSLLDI256, UNKNOWN, (int) V8SI_FTYPE_V8SI_SI_COUNT },
@@ -25872,7 +26326,7 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX2, CODE_FOR_ashrv16hi3, "__builtin_ia32_psraw256", IX86_BUILTIN_PSRAW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V8HI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_ashrv8si3, "__builtin_ia32_psradi256", IX86_BUILTIN_PSRADI256, UNKNOWN, (int) V8SI_FTYPE_V8SI_SI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_ashrv8si3, "__builtin_ia32_psrad256", IX86_BUILTIN_PSRAD256, UNKNOWN, (int) V8SI_FTYPE_V8SI_V4SI_COUNT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshrqv4di3, "__builtin_ia32_psrldqi256", IX86_BUILTIN_PSRLDQI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_INT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshrv2ti3, "__builtin_ia32_psrldqi256", IX86_BUILTIN_PSRLDQI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_INT_CONVERT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_lshrv16hi3, "__builtin_ia32_psrlwi256", IX86_BUILTIN_PSRLWI256 , UNKNOWN, (int) V16HI_FTYPE_V16HI_SI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_lshrv16hi3, "__builtin_ia32_psrlw256", IX86_BUILTIN_PSRLW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V8HI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_lshrv8si3, "__builtin_ia32_psrldi256", IX86_BUILTIN_PSRLDI256, UNKNOWN, (int) V8SI_FTYPE_V8SI_SI_COUNT },
@@ -27502,6 +27956,11 @@ ix86_expand_args_builtin (const struct builtin_description *d,
rmode = V1TImode;
nargs_constant = 1;
break;
+ case V4DI_FTYPE_V4DI_INT_CONVERT:
+ nargs = 2;
+ rmode = V2TImode;
+ nargs_constant = 1;
+ break;
case V8HI_FTYPE_V8HI_INT:
case V8HI_FTYPE_V8SF_INT:
case V8HI_FTYPE_V4SF_INT:
@@ -27779,7 +28238,6 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
klass = store;
memory = 0;
break;
- break;
case UINT64_FTYPE_VOID:
case UNSIGNED_FTYPE_VOID:
nargs = 0;
@@ -28432,7 +28890,6 @@ rdrand_step:
op4 = expand_normal (arg4);
/* Note the arg order is different from the operand order. */
mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
mode2 = insn_data[icode].operand[3].mode;
mode3 = insn_data[icode].operand[4].mode;
mode4 = insn_data[icode].operand[5].mode;
@@ -28446,12 +28903,11 @@ rdrand_step:
if (GET_MODE (op1) != Pmode)
op1 = convert_to_mode (Pmode, op1, 1);
op1 = force_reg (Pmode, op1);
- op1 = gen_rtx_MEM (mode1, op1);
if (!insn_data[icode].operand[1].predicate (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
- if (!insn_data[icode].operand[2].predicate (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
+ if (!insn_data[icode].operand[2].predicate (op1, Pmode))
+ op1 = copy_to_mode_reg (Pmode, op1);
if (!insn_data[icode].operand[3].predicate (op2, mode2))
op2 = copy_to_mode_reg (mode2, op2);
if (!insn_data[icode].operand[4].predicate (op3, mode3))
@@ -28844,7 +29300,7 @@ ix86_veclibabi_svml (enum built_in_function fn, tree type_out, tree type_in)
return NULL_TREE;
}
- bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls[fn]));
+ bname = IDENTIFIER_POINTER (DECL_NAME (builtin_decl_implicit (fn)));
if (fn == BUILT_IN_LOGF)
strcpy (name, "vmlsLn4");
@@ -28862,7 +29318,8 @@ ix86_veclibabi_svml (enum built_in_function fn, tree type_out, tree type_in)
name[4] &= ~0x20;
arity = 0;
- for (args = DECL_ARGUMENTS (implicit_built_in_decls[fn]); args;
+ for (args = DECL_ARGUMENTS (builtin_decl_implicit (fn));
+ args;
args = TREE_CHAIN (args))
arity++;
@@ -28943,11 +29400,12 @@ ix86_veclibabi_acml (enum built_in_function fn, tree type_out, tree type_in)
return NULL_TREE;
}
- bname = IDENTIFIER_POINTER (DECL_NAME (implicit_built_in_decls[fn]));
+ bname = IDENTIFIER_POINTER (DECL_NAME (builtin_decl_implicit (fn)));
sprintf (name + 7, "%s", bname+10);
arity = 0;
- for (args = DECL_ARGUMENTS (implicit_built_in_decls[fn]); args;
+ for (args = DECL_ARGUMENTS (builtin_decl_implicit (fn));
+ args;
args = TREE_CHAIN (args))
arity++;
@@ -30799,7 +31257,7 @@ x86_output_mi_thunk (FILE *file,
}
}
- emit_insn (ix86_gen_add3 (delta_dst, delta_dst, delta_rtx));
+ ix86_emit_binop (PLUS, Pmode, delta_dst, delta_rtx);
}
/* Adjust the this parameter by a value stored in the vtable. */
@@ -30842,7 +31300,7 @@ x86_output_mi_thunk (FILE *file,
REGNO (this_reg)),
vcall_mem));
else
- emit_insn (ix86_gen_add3 (this_reg, this_reg, vcall_mem));
+ ix86_emit_binop (PLUS, Pmode, this_reg, vcall_mem);
}
/* If necessary, drop THIS back to its stack slot. */
@@ -31189,7 +31647,7 @@ ix86_pad_returns (void)
}
if (replace)
{
- emit_jump_insn_before (gen_return_internal_long (), ret);
+ emit_jump_insn_before (gen_simple_return_internal_long (), ret);
delete_insn (ret);
}
}
@@ -31457,9 +31915,9 @@ x86_emit_floatuns (rtx operands[2])
emit_label (donelab);
}
-/* AVX does not support 32-byte integer vector operations,
- thus the longest vector we are faced with is V16QImode. */
-#define MAX_VECT_LEN 16
+/* AVX2 does support 32-byte integer vector operations,
+ thus the longest vector we are faced with is V32QImode. */
+#define MAX_VECT_LEN 32
struct expand_vec_perm_d
{
@@ -31472,6 +31930,9 @@ struct expand_vec_perm_d
static bool expand_vec_perm_1 (struct expand_vec_perm_d *d);
static bool expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d);
+static int extract_vec_perm_cst (struct expand_vec_perm_d *, tree);
+static bool ix86_vectorize_builtin_vec_perm_ok (tree vec_type, tree mask);
+
/* Get a vector mode of the same size as the original but with elements
twice as wide. This is only guaranteed to apply to integral vectors. */
@@ -32793,72 +33254,100 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
}
}
-/* Expand a vector reduction. FN is the binary pattern to reduce;
- DEST is the destination; IN is the input vector. */
+/* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
+ to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
+ The upper bits of DEST are undefined, though they shouldn't cause
+ exceptions (some bits from src or all zeros are ok). */
-void
-ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
+static void
+emit_reduc_half (rtx dest, rtx src, int i)
{
- rtx tmp1, tmp2, tmp3, tmp4, tmp5;
- enum machine_mode mode = GET_MODE (in);
- int i;
-
- tmp1 = gen_reg_rtx (mode);
- tmp2 = gen_reg_rtx (mode);
- tmp3 = gen_reg_rtx (mode);
-
- switch (mode)
+ rtx tem;
+ switch (GET_MODE (src))
{
case V4SFmode:
- emit_insn (gen_sse_movhlps (tmp1, in, in));
- emit_insn (fn (tmp2, tmp1, in));
- emit_insn (gen_sse_shufps_v4sf (tmp3, tmp2, tmp2,
- const1_rtx, const1_rtx,
- GEN_INT (1+4), GEN_INT (1+4)));
+ if (i == 128)
+ tem = gen_sse_movhlps (dest, src, src);
+ else
+ tem = gen_sse_shufps_v4sf (dest, src, src, const1_rtx, const1_rtx,
+ GEN_INT (1 + 4), GEN_INT (1 + 4));
+ break;
+ case V2DFmode:
+ tem = gen_vec_interleave_highv2df (dest, src, src);
+ break;
+ case V16QImode:
+ case V8HImode:
+ case V4SImode:
+ case V2DImode:
+ tem = gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, dest),
+ gen_lowpart (V1TImode, src),
+ GEN_INT (i / 2));
break;
case V8SFmode:
- tmp4 = gen_reg_rtx (mode);
- tmp5 = gen_reg_rtx (mode);
- emit_insn (gen_avx_vperm2f128v8sf3 (tmp4, in, in, const1_rtx));
- emit_insn (fn (tmp5, tmp4, in));
- emit_insn (gen_avx_shufps256 (tmp1, tmp5, tmp5, GEN_INT (2+12)));
- emit_insn (fn (tmp2, tmp1, tmp5));
- emit_insn (gen_avx_shufps256 (tmp3, tmp2, tmp2, const1_rtx));
+ if (i == 256)
+ tem = gen_avx_vperm2f128v8sf3 (dest, src, src, const1_rtx);
+ else
+ tem = gen_avx_shufps256 (dest, src, src,
+ GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
break;
case V4DFmode:
- emit_insn (gen_avx_vperm2f128v4df3 (tmp1, in, in, const1_rtx));
- emit_insn (fn (tmp2, tmp1, in));
- emit_insn (gen_avx_shufpd256 (tmp3, tmp2, tmp2, const1_rtx));
+ if (i == 256)
+ tem = gen_avx_vperm2f128v4df3 (dest, src, src, const1_rtx);
+ else
+ tem = gen_avx_shufpd256 (dest, src, src, const1_rtx);
break;
case V32QImode:
case V16HImode:
case V8SImode:
case V4DImode:
- emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, tmp1),
- gen_lowpart (V4DImode, in),
- gen_lowpart (V4DImode, in),
- const1_rtx));
- tmp4 = in;
- tmp5 = tmp1;
- for (i = 64; i >= GET_MODE_BITSIZE (GET_MODE_INNER (mode)); i >>= 1)
- {
- if (i != 64)
- {
- tmp2 = gen_reg_rtx (mode);
- tmp3 = gen_reg_rtx (mode);
- }
- emit_insn (fn (tmp2, tmp4, tmp5));
- emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, tmp3),
- gen_lowpart (V2TImode, tmp2),
- GEN_INT (i)));
- tmp4 = tmp2;
- tmp5 = tmp3;
- }
+ if (i == 256)
+ tem = gen_avx2_permv2ti (gen_lowpart (V4DImode, dest),
+ gen_lowpart (V4DImode, src),
+ gen_lowpart (V4DImode, src),
+ const1_rtx);
+ else
+ tem = gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, dest),
+ gen_lowpart (V2TImode, src),
+ GEN_INT (i / 2));
break;
default:
gcc_unreachable ();
}
- emit_insn (fn (dest, tmp2, tmp3));
+ emit_insn (tem);
+}
+
+/* Expand a vector reduction. FN is the binary pattern to reduce;
+ DEST is the destination; IN is the input vector. */
+
+void
+ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
+{
+ rtx half, dst, vec = in;
+ enum machine_mode mode = GET_MODE (in);
+ int i;
+
+ /* SSE4 has a special instruction for V8HImode UMIN reduction. */
+ if (TARGET_SSE4_1
+ && mode == V8HImode
+ && fn == gen_uminv8hi3)
+ {
+ emit_insn (gen_sse4_1_phminposuw (dest, in));
+ return;
+ }
+
+ for (i = GET_MODE_BITSIZE (mode);
+ i > GET_MODE_BITSIZE (GET_MODE_INNER (mode));
+ i >>= 1)
+ {
+ half = gen_reg_rtx (mode);
+ emit_reduc_half (half, vec, i);
+ if (i == GET_MODE_BITSIZE (GET_MODE_INNER (mode)) * 2)
+ dst = dest;
+ else
+ dst = gen_reg_rtx (mode);
+ emit_insn (fn (dst, half, vec));
+ vec = dst;
+ }
}
/* Target hook for scalar_mode_supported_p. */
@@ -33103,7 +33592,7 @@ void ix86_emit_i387_round (rtx op0, rtx op1)
res = gen_reg_rtx (outmode);
half = CONST_DOUBLE_FROM_REAL_VALUE (dconsthalf, inmode);
-
+
/* round(a) = sgn(a) * floor(fabs(a) + 0.5) */
/* scratch = fxam(op1) */
@@ -34263,7 +34752,7 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
}
/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
- in terms of blendp[sd] / pblendw / pblendvb. */
+ in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
static bool
expand_vec_perm_blend (struct expand_vec_perm_d *d)
@@ -34271,10 +34760,17 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
enum machine_mode vmode = d->vmode;
unsigned i, mask, nelt = d->nelt;
rtx target, op0, op1, x;
+ rtx rperm[32], vperm;
- if (!TARGET_SSE4_1 || d->op0 == d->op1)
+ if (d->op0 == d->op1)
return false;
- if (!(GET_MODE_SIZE (vmode) == 16 || vmode == V4DFmode || vmode == V8SFmode))
+ if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
+ ;
+ else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
+ ;
+ else if (TARGET_SSE4_1 && GET_MODE_SIZE (vmode) == 16)
+ ;
+ else
return false;
/* This is a blend, not a permute. Elements must stay in their
@@ -34292,30 +34788,6 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
/* ??? Without SSE4.1, we could implement this with and/andn/or. This
decision should be extracted elsewhere, so that we only try that
sequence once all budget==3 options have been tried. */
-
- /* For bytes, see if bytes move in pairs so we can use pblendw with
- an immediate argument, rather than pblendvb with a vector argument. */
- if (vmode == V16QImode)
- {
- bool pblendw_ok = true;
- for (i = 0; i < 16 && pblendw_ok; i += 2)
- pblendw_ok = (d->perm[i] + 1 == d->perm[i + 1]);
-
- if (!pblendw_ok)
- {
- rtx rperm[16], vperm;
-
- for (i = 0; i < nelt; ++i)
- rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
-
- vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm));
- vperm = force_reg (V16QImode, vperm);
-
- emit_insn (gen_sse4_1_pblendvb (d->target, d->op0, d->op1, vperm));
- return true;
- }
- }
-
target = d->target;
op0 = d->op0;
op1 = d->op1;
@@ -34328,6 +34800,7 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
case V2DFmode:
case V4SFmode:
case V8HImode:
+ case V8SImode:
for (i = 0; i < nelt; ++i)
mask |= (d->perm[i] >= nelt) << i;
break;
@@ -34335,24 +34808,122 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
case V2DImode:
for (i = 0; i < 2; ++i)
mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
+ vmode = V8HImode;
goto do_subreg;
case V4SImode:
for (i = 0; i < 4; ++i)
mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
+ vmode = V8HImode;
goto do_subreg;
case V16QImode:
+ /* See if bytes move in pairs so we can use pblendw with
+ an immediate argument, rather than pblendvb with a vector
+ argument. */
+ for (i = 0; i < 16; i += 2)
+ if (d->perm[i] + 1 != d->perm[i + 1])
+ {
+ use_pblendvb:
+ for (i = 0; i < nelt; ++i)
+ rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
+
+ finish_pblendvb:
+ vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm));
+ vperm = force_reg (vmode, vperm);
+
+ if (GET_MODE_SIZE (vmode) == 16)
+ emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
+ else
+ emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
+ return true;
+ }
+
for (i = 0; i < 8; ++i)
mask |= (d->perm[i * 2] >= 16) << i;
+ vmode = V8HImode;
+ /* FALLTHRU */
do_subreg:
- vmode = V8HImode;
target = gen_lowpart (vmode, target);
op0 = gen_lowpart (vmode, op0);
op1 = gen_lowpart (vmode, op1);
break;
+ case V32QImode:
+ /* See if bytes move in pairs. If not, vpblendvb must be used. */
+ for (i = 0; i < 32; i += 2)
+ if (d->perm[i] + 1 != d->perm[i + 1])
+ goto use_pblendvb;
+ /* See if bytes move in quadruplets. If yes, vpblendd
+ with immediate can be used. */
+ for (i = 0; i < 32; i += 4)
+ if (d->perm[i] + 2 != d->perm[i + 2])
+ break;
+ if (i < 32)
+ {
+ /* See if bytes move the same in both lanes. If yes,
+ vpblendw with immediate can be used. */
+ for (i = 0; i < 16; i += 2)
+ if (d->perm[i] + 16 != d->perm[i + 16])
+ goto use_pblendvb;
+
+ /* Use vpblendw. */
+ for (i = 0; i < 16; ++i)
+ mask |= (d->perm[i * 2] >= 32) << i;
+ vmode = V16HImode;
+ goto do_subreg;
+ }
+
+ /* Use vpblendd. */
+ for (i = 0; i < 8; ++i)
+ mask |= (d->perm[i * 4] >= 32) << i;
+ vmode = V8SImode;
+ goto do_subreg;
+
+ case V16HImode:
+ /* See if words move in pairs. If yes, vpblendd can be used. */
+ for (i = 0; i < 16; i += 2)
+ if (d->perm[i] + 1 != d->perm[i + 1])
+ break;
+ if (i < 16)
+ {
+ /* See if words move the same in both lanes. If not,
+ vpblendvb must be used. */
+ for (i = 0; i < 8; i++)
+ if (d->perm[i] + 8 != d->perm[i + 8])
+ {
+ /* Use vpblendvb. */
+ for (i = 0; i < 32; ++i)
+ rperm[i] = (d->perm[i / 2] < 16 ? const0_rtx : constm1_rtx);
+
+ vmode = V32QImode;
+ nelt = 32;
+ target = gen_lowpart (vmode, target);
+ op0 = gen_lowpart (vmode, op0);
+ op1 = gen_lowpart (vmode, op1);
+ goto finish_pblendvb;
+ }
+
+ /* Use vpblendw. */
+ for (i = 0; i < 16; ++i)
+ mask |= (d->perm[i] >= 16) << i;
+ break;
+ }
+
+ /* Use vpblendd. */
+ for (i = 0; i < 8; ++i)
+ mask |= (d->perm[i * 2] >= 16) << i;
+ vmode = V8SImode;
+ goto do_subreg;
+
+ case V4DImode:
+ /* Use vpblendd. */
+ for (i = 0; i < 4; ++i)
+ mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
+ vmode = V8SImode;
+ goto do_subreg;
+
default:
gcc_unreachable ();
}
@@ -34413,43 +34984,165 @@ expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
return true;
}
-/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
- in terms of pshufb or vpperm. */
+/* Return true if permutation D can be performed as VMODE permutation
+ instead. */
static bool
-expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
+valid_perm_using_mode_p (enum machine_mode vmode, struct expand_vec_perm_d *d)
{
- unsigned i, nelt, eltsz;
- rtx rperm[16], vperm, target, op0, op1;
+ unsigned int i, j, chunk;
- if (!(d->op0 == d->op1 ? TARGET_SSSE3 : TARGET_XOP))
- return false;
- if (GET_MODE_SIZE (d->vmode) != 16)
+ if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT
+ || GET_MODE_CLASS (d->vmode) != MODE_VECTOR_INT
+ || GET_MODE_SIZE (vmode) != GET_MODE_SIZE (d->vmode))
return false;
- if (d->testing_p)
+ if (GET_MODE_NUNITS (vmode) >= d->nelt)
return true;
+ chunk = d->nelt / GET_MODE_NUNITS (vmode);
+ for (i = 0; i < d->nelt; i += chunk)
+ if (d->perm[i] & (chunk - 1))
+ return false;
+ else
+ for (j = 1; j < chunk; ++j)
+ if (d->perm[i] + j != d->perm[i + j])
+ return false;
+
+ return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
+ in terms of pshufb, vpperm, vpermq, vpermd or vperm2i128. */
+
+static bool
+expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
+{
+ unsigned i, nelt, eltsz, mask;
+ unsigned char perm[32];
+ enum machine_mode vmode = V16QImode;
+ rtx rperm[32], vperm, target, op0, op1;
+
nelt = d->nelt;
- eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
- for (i = 0; i < nelt; ++i)
+ if (d->op0 != d->op1)
{
- unsigned j, e = d->perm[i];
- for (j = 0; j < eltsz; ++j)
- rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
+ if (!TARGET_XOP || GET_MODE_SIZE (d->vmode) != 16)
+ {
+ if (TARGET_AVX2
+ && valid_perm_using_mode_p (V2TImode, d))
+ {
+ if (d->testing_p)
+ return true;
+
+ /* Use vperm2i128 insn. The pattern uses
+ V4DImode instead of V2TImode. */
+ target = gen_lowpart (V4DImode, d->target);
+ op0 = gen_lowpart (V4DImode, d->op0);
+ op1 = gen_lowpart (V4DImode, d->op1);
+ rperm[0]
+ = GEN_INT (((d->perm[0] & (nelt / 2)) ? 1 : 0)
+ || ((d->perm[nelt / 2] & (nelt / 2)) ? 2 : 0));
+ emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
+ return true;
+ }
+ return false;
+ }
}
+ else
+ {
+ if (GET_MODE_SIZE (d->vmode) == 16)
+ {
+ if (!TARGET_SSSE3)
+ return false;
+ }
+ else if (GET_MODE_SIZE (d->vmode) == 32)
+ {
+ if (!TARGET_AVX2)
+ return false;
- vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm));
- vperm = force_reg (V16QImode, vperm);
+ /* V4DImode should be already handled through
+ expand_vselect by vpermq instruction. */
+ gcc_assert (d->vmode != V4DImode);
+
+ vmode = V32QImode;
+ if (d->vmode == V8SImode
+ || d->vmode == V16HImode
+ || d->vmode == V32QImode)
+ {
+ /* First see if vpermq can be used for
+ V8SImode/V16HImode/V32QImode. */
+ if (valid_perm_using_mode_p (V4DImode, d))
+ {
+ for (i = 0; i < 4; i++)
+ perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
+ if (d->testing_p)
+ return true;
+ return expand_vselect (gen_lowpart (V4DImode, d->target),
+ gen_lowpart (V4DImode, d->op0),
+ perm, 4);
+ }
+
+ /* Next see if vpermd can be used. */
+ if (valid_perm_using_mode_p (V8SImode, d))
+ vmode = V8SImode;
+ }
- target = gen_lowpart (V16QImode, d->target);
- op0 = gen_lowpart (V16QImode, d->op0);
+ if (vmode == V32QImode)
+ {
+ /* vpshufb only works intra lanes, it is not
+ possible to shuffle bytes in between the lanes. */
+ for (i = 0; i < nelt; ++i)
+ if ((d->perm[i] ^ i) & (nelt / 2))
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+
+ if (d->testing_p)
+ return true;
+
+ if (vmode == V8SImode)
+ for (i = 0; i < 8; ++i)
+ rperm[i] = GEN_INT ((d->perm[i * nelt / 8] * 8 / nelt) & 7);
+ else
+ {
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+ if (d->op0 != d->op1)
+ mask = 2 * nelt - 1;
+ else if (vmode == V16QImode)
+ mask = nelt - 1;
+ else
+ mask = nelt / 2 - 1;
+
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & mask;
+ for (j = 0; j < eltsz; ++j)
+ rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
+ }
+ }
+
+ vperm = gen_rtx_CONST_VECTOR (vmode,
+ gen_rtvec_v (GET_MODE_NUNITS (vmode), rperm));
+ vperm = force_reg (vmode, vperm);
+
+ target = gen_lowpart (vmode, d->target);
+ op0 = gen_lowpart (vmode, d->op0);
if (d->op0 == d->op1)
- emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, vperm));
+ {
+ if (vmode == V16QImode)
+ emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, vperm));
+ else if (vmode == V32QImode)
+ emit_insn (gen_avx2_pshufbv32qi3 (target, op0, vperm));
+ else
+ emit_insn (gen_avx2_permvarv8si (target, vperm, op0));
+ }
else
{
- op1 = gen_lowpart (V16QImode, d->op1);
+ op1 = gen_lowpart (vmode, d->op1);
emit_insn (gen_xop_pperm (target, op0, op1, vperm));
}
@@ -34471,9 +35164,58 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
if (d->op0 == d->op1)
{
int mask = nelt - 1;
+ bool identity_perm = true;
+ bool broadcast_perm = true;
for (i = 0; i < nelt; i++)
- perm2[i] = d->perm[i] & mask;
+ {
+ perm2[i] = d->perm[i] & mask;
+ if (perm2[i] != i)
+ identity_perm = false;
+ if (perm2[i])
+ broadcast_perm = false;
+ }
+
+ if (identity_perm)
+ {
+ if (!d->testing_p)
+ emit_move_insn (d->target, d->op0);
+ return true;
+ }
+ else if (broadcast_perm && TARGET_AVX2)
+ {
+ /* Use vpbroadcast{b,w,d}. */
+ rtx op = d->op0, (*gen) (rtx, rtx) = NULL;
+ switch (d->vmode)
+ {
+ case V32QImode:
+ op = gen_lowpart (V16QImode, op);
+ gen = gen_avx2_pbroadcastv32qi;
+ break;
+ case V16HImode:
+ op = gen_lowpart (V8HImode, op);
+ gen = gen_avx2_pbroadcastv16hi;
+ break;
+ case V8SImode:
+ op = gen_lowpart (V4SImode, op);
+ gen = gen_avx2_pbroadcastv8si;
+ break;
+ case V16QImode:
+ gen = gen_avx2_pbroadcastv16qi;
+ break;
+ case V8HImode:
+ gen = gen_avx2_pbroadcastv8hi;
+ break;
+ /* For other modes prefer other shuffles this function creates. */
+ default: break;
+ }
+ if (gen != NULL)
+ {
+ if (!d->testing_p)
+ emit_insn (gen (d->target, op));
+ return true;
+ }
+ }
if (expand_vselect (d->target, d->op0, perm2, nelt))
return true;
@@ -34537,7 +35279,8 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
if (expand_vec_perm_vpermil (d))
return true;
- /* Try the SSSE3 pshufb or XOP vpperm variable permutation. */
+ /* Try the SSSE3 pshufb or XOP vpperm or AVX2 vperm2i128,
+ vpshufb, vpermd or vpermq variable permutation. */
if (expand_vec_perm_pshufb (d))
return true;
@@ -34656,93 +35399,210 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
{
struct expand_vec_perm_d dremap, dfinal;
unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
- unsigned contents, h1, h2, h3, h4;
+ unsigned HOST_WIDE_INT contents;
unsigned char remap[2 * MAX_VECT_LEN];
rtx seq;
- bool ok;
-
- if (d->op0 == d->op1)
- return false;
+ bool ok, same_halves = false;
- /* The 256-bit unpck[lh]p[sd] instructions only operate within the 128-bit
- lanes. We can use similar techniques with the vperm2f128 instruction,
- but it requires slightly different logic. */
- if (GET_MODE_SIZE (d->vmode) != 16)
+ if (GET_MODE_SIZE (d->vmode) == 16)
+ {
+ if (d->op0 == d->op1)
+ return false;
+ }
+ else if (GET_MODE_SIZE (d->vmode) == 32)
+ {
+ if (!TARGET_AVX)
+ return false;
+ /* For 32-byte modes allow even d->op0 == d->op1.
+ The lack of cross-lane shuffling in some instructions
+ might prevent a single insn shuffle. */
+ }
+ else
return false;
/* Examine from whence the elements come. */
contents = 0;
for (i = 0; i < nelt; ++i)
- contents |= 1u << d->perm[i];
-
- /* Split the two input vectors into 4 halves. */
- h1 = (1u << nelt2) - 1;
- h2 = h1 << nelt2;
- h3 = h2 << nelt2;
- h4 = h3 << nelt2;
+ contents |= ((unsigned HOST_WIDE_INT) 1) << d->perm[i];
memset (remap, 0xff, sizeof (remap));
dremap = *d;
- /* If the elements from the low halves use interleave low, and similarly
- for interleave high. If the elements are from mis-matched halves, we
- can use shufps for V4SF/V4SI or do a DImode shuffle. */
- if ((contents & (h1 | h3)) == contents)
+ if (GET_MODE_SIZE (d->vmode) == 16)
{
- for (i = 0; i < nelt2; ++i)
+ unsigned HOST_WIDE_INT h1, h2, h3, h4;
+
+ /* Split the two input vectors into 4 halves. */
+ h1 = (((unsigned HOST_WIDE_INT) 1) << nelt2) - 1;
+ h2 = h1 << nelt2;
+ h3 = h2 << nelt2;
+ h4 = h3 << nelt2;
+
+ /* If the elements from the low halves use interleave low, and similarly
+ for interleave high. If the elements are from mis-matched halves, we
+ can use shufps for V4SF/V4SI or do a DImode shuffle. */
+ if ((contents & (h1 | h3)) == contents)
{
- remap[i] = i * 2;
- remap[i + nelt] = i * 2 + 1;
- dremap.perm[i * 2] = i;
- dremap.perm[i * 2 + 1] = i + nelt;
+ /* punpckl* */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i] = i * 2;
+ remap[i + nelt] = i * 2 + 1;
+ dremap.perm[i * 2] = i;
+ dremap.perm[i * 2 + 1] = i + nelt;
+ }
}
- }
- else if ((contents & (h2 | h4)) == contents)
- {
- for (i = 0; i < nelt2; ++i)
+ else if ((contents & (h2 | h4)) == contents)
{
- remap[i + nelt2] = i * 2;
- remap[i + nelt + nelt2] = i * 2 + 1;
- dremap.perm[i * 2] = i + nelt2;
- dremap.perm[i * 2 + 1] = i + nelt + nelt2;
+ /* punpckh* */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i + nelt2] = i * 2;
+ remap[i + nelt + nelt2] = i * 2 + 1;
+ dremap.perm[i * 2] = i + nelt2;
+ dremap.perm[i * 2 + 1] = i + nelt + nelt2;
+ }
}
- }
- else if ((contents & (h1 | h4)) == contents)
- {
- for (i = 0; i < nelt2; ++i)
+ else if ((contents & (h1 | h4)) == contents)
{
- remap[i] = i;
- remap[i + nelt + nelt2] = i + nelt2;
- dremap.perm[i] = i;
- dremap.perm[i + nelt2] = i + nelt + nelt2;
+ /* shufps */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i] = i;
+ remap[i + nelt + nelt2] = i + nelt2;
+ dremap.perm[i] = i;
+ dremap.perm[i + nelt2] = i + nelt + nelt2;
+ }
+ if (nelt != 4)
+ {
+ /* shufpd */
+ dremap.vmode = V2DImode;
+ dremap.nelt = 2;
+ dremap.perm[0] = 0;
+ dremap.perm[1] = 3;
+ }
}
- if (nelt != 4)
+ else if ((contents & (h2 | h3)) == contents)
{
- dremap.vmode = V2DImode;
- dremap.nelt = 2;
- dremap.perm[0] = 0;
- dremap.perm[1] = 3;
+ /* shufps */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i + nelt2] = i;
+ remap[i + nelt] = i + nelt2;
+ dremap.perm[i] = i + nelt2;
+ dremap.perm[i + nelt2] = i + nelt;
+ }
+ if (nelt != 4)
+ {
+ /* shufpd */
+ dremap.vmode = V2DImode;
+ dremap.nelt = 2;
+ dremap.perm[0] = 1;
+ dremap.perm[1] = 2;
+ }
}
+ else
+ return false;
}
- else if ((contents & (h2 | h3)) == contents)
+ else
{
- for (i = 0; i < nelt2; ++i)
+ unsigned int nelt4 = nelt / 4, nzcnt = 0;
+ unsigned HOST_WIDE_INT q[8];
+ unsigned int nonzero_halves[4];
+
+ /* Split the two input vectors into 8 quarters. */
+ q[0] = (((unsigned HOST_WIDE_INT) 1) << nelt4) - 1;
+ for (i = 1; i < 8; ++i)
+ q[i] = q[0] << (nelt4 * i);
+ for (i = 0; i < 4; ++i)
+ if (((q[2 * i] | q[2 * i + 1]) & contents) != 0)
+ {
+ nonzero_halves[nzcnt] = i;
+ ++nzcnt;
+ }
+
+ if (nzcnt == 1)
{
- remap[i + nelt2] = i;
- remap[i + nelt] = i + nelt2;
- dremap.perm[i] = i + nelt2;
- dremap.perm[i + nelt2] = i + nelt;
+ gcc_assert (d->op0 == d->op1);
+ nonzero_halves[1] = nonzero_halves[0];
+ same_halves = true;
}
- if (nelt != 4)
+ else if (d->op0 == d->op1)
{
- dremap.vmode = V2DImode;
- dremap.nelt = 2;
- dremap.perm[0] = 1;
- dremap.perm[1] = 2;
+ gcc_assert (nonzero_halves[0] == 0);
+ gcc_assert (nonzero_halves[1] == 1);
}
+
+ if (nzcnt <= 2)
+ {
+ if (d->perm[0] / nelt2 == nonzero_halves[1])
+ {
+ /* Attempt to increase the likelyhood that dfinal
+ shuffle will be intra-lane. */
+ char tmph = nonzero_halves[0];
+ nonzero_halves[0] = nonzero_halves[1];
+ nonzero_halves[1] = tmph;
+ }
+
+ /* vperm2f128 or vperm2i128. */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i + nonzero_halves[1] * nelt2] = i + nelt2;
+ remap[i + nonzero_halves[0] * nelt2] = i;
+ dremap.perm[i + nelt2] = i + nonzero_halves[1] * nelt2;
+ dremap.perm[i] = i + nonzero_halves[0] * nelt2;
+ }
+
+ if (d->vmode != V8SFmode
+ && d->vmode != V4DFmode
+ && d->vmode != V8SImode)
+ {
+ dremap.vmode = V8SImode;
+ dremap.nelt = 8;
+ for (i = 0; i < 4; ++i)
+ {
+ dremap.perm[i] = i + nonzero_halves[0] * 4;
+ dremap.perm[i + 4] = i + nonzero_halves[1] * 4;
+ }
+ }
+ }
+ else if (d->op0 == d->op1)
+ return false;
+ else if (TARGET_AVX2
+ && (contents & (q[0] | q[2] | q[4] | q[6])) == contents)
+ {
+ /* vpunpckl* */
+ for (i = 0; i < nelt4; ++i)
+ {
+ remap[i] = i * 2;
+ remap[i + nelt] = i * 2 + 1;
+ remap[i + nelt2] = i * 2 + nelt2;
+ remap[i + nelt + nelt2] = i * 2 + nelt2 + 1;
+ dremap.perm[i * 2] = i;
+ dremap.perm[i * 2 + 1] = i + nelt;
+ dremap.perm[i * 2 + nelt2] = i + nelt2;
+ dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2;
+ }
+ }
+ else if (TARGET_AVX2
+ && (contents & (q[1] | q[3] | q[5] | q[7])) == contents)
+ {
+ /* vpunpckh* */
+ for (i = 0; i < nelt4; ++i)
+ {
+ remap[i + nelt4] = i * 2;
+ remap[i + nelt + nelt4] = i * 2 + 1;
+ remap[i + nelt2 + nelt4] = i * 2 + nelt2;
+ remap[i + nelt + nelt2 + nelt4] = i * 2 + nelt2 + 1;
+ dremap.perm[i * 2] = i + nelt4;
+ dremap.perm[i * 2 + 1] = i + nelt + nelt4;
+ dremap.perm[i * 2 + nelt2] = i + nelt2 + nelt4;
+ dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2 + nelt4;
+ }
+ }
+ else
+ return false;
}
- else
- return false;
/* Use the remapping array set up above to move the elements from their
swizzled locations into their final destinations. */
@@ -34751,7 +35611,15 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
{
unsigned e = remap[d->perm[i]];
gcc_assert (e < nelt);
- dfinal.perm[i] = e;
+ /* If same_halves is true, both halves of the remapped vector are the
+ same. Avoid cross-lane accesses if possible. */
+ if (same_halves && i >= nelt2)
+ {
+ gcc_assert (e < nelt2);
+ dfinal.perm[i] = e + nelt2;
+ }
+ else
+ dfinal.perm[i] = e;
}
dfinal.op0 = gen_reg_rtx (dfinal.vmode);
dfinal.op1 = dfinal.op0;
@@ -34767,6 +35635,9 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
if (!ok)
return false;
+ if (d->testing_p)
+ return true;
+
if (dremap.vmode != dfinal.vmode)
{
dremap.target = gen_lowpart (dremap.vmode, dremap.target);
@@ -34781,6 +35652,159 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
return true;
}
+/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to simplify
+ a single vector cross-lane permutation into vpermq followed
+ by any of the single insn permutations. */
+
+static bool
+expand_vec_perm_vpermq_perm_1 (struct expand_vec_perm_d *d)
+{
+ struct expand_vec_perm_d dremap, dfinal;
+ unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, nelt4 = nelt / 4;
+ unsigned contents[2];
+ bool ok;
+
+ if (!(TARGET_AVX2
+ && (d->vmode == V32QImode || d->vmode == V16HImode)
+ && d->op0 == d->op1))
+ return false;
+
+ contents[0] = 0;
+ contents[1] = 0;
+ for (i = 0; i < nelt2; ++i)
+ {
+ contents[0] |= 1u << (d->perm[i] / nelt4);
+ contents[1] |= 1u << (d->perm[i + nelt2] / nelt4);
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ unsigned int cnt = 0;
+ for (j = 0; j < 4; ++j)
+ if ((contents[i] & (1u << j)) != 0 && ++cnt > 2)
+ return false;
+ }
+
+ if (d->testing_p)
+ return true;
+
+ dremap = *d;
+ dremap.vmode = V4DImode;
+ dremap.nelt = 4;
+ dremap.target = gen_reg_rtx (V4DImode);
+ dremap.op0 = gen_lowpart (V4DImode, d->op0);
+ dremap.op1 = dremap.op0;
+ for (i = 0; i < 2; ++i)
+ {
+ unsigned int cnt = 0;
+ for (j = 0; j < 4; ++j)
+ if ((contents[i] & (1u << j)) != 0)
+ dremap.perm[2 * i + cnt++] = j;
+ for (; cnt < 2; ++cnt)
+ dremap.perm[2 * i + cnt] = 0;
+ }
+
+ dfinal = *d;
+ dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
+ dfinal.op1 = dfinal.op0;
+ for (i = 0, j = 0; i < nelt; ++i)
+ {
+ if (i == nelt2)
+ j = 2;
+ dfinal.perm[i] = (d->perm[i] & (nelt4 - 1)) | (j ? nelt2 : 0);
+ if ((d->perm[i] / nelt4) == dremap.perm[j])
+ ;
+ else if ((d->perm[i] / nelt4) == dremap.perm[j + 1])
+ dfinal.perm[i] |= nelt4;
+ else
+ gcc_unreachable ();
+ }
+
+ ok = expand_vec_perm_1 (&dremap);
+ gcc_assert (ok);
+
+ ok = expand_vec_perm_1 (&dfinal);
+ gcc_assert (ok);
+
+ return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to simplify
+ a two vector permutation using 2 intra-lane interleave insns
+ and cross-lane shuffle for 32-byte vectors. */
+
+static bool
+expand_vec_perm_interleave3 (struct expand_vec_perm_d *d)
+{
+ unsigned i, nelt;
+ rtx (*gen) (rtx, rtx, rtx);
+
+ if (d->op0 == d->op1)
+ return false;
+ if (TARGET_AVX2 && GET_MODE_SIZE (d->vmode) == 32)
+ ;
+ else if (TARGET_AVX && (d->vmode == V8SFmode || d->vmode == V4DFmode))
+ ;
+ else
+ return false;
+
+ nelt = d->nelt;
+ if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
+ return false;
+ for (i = 0; i < nelt; i += 2)
+ if (d->perm[i] != d->perm[0] + i / 2
+ || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ switch (d->vmode)
+ {
+ case V32QImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv32qi;
+ else
+ gen = gen_vec_interleave_lowv32qi;
+ break;
+ case V16HImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv16hi;
+ else
+ gen = gen_vec_interleave_lowv16hi;
+ break;
+ case V8SImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv8si;
+ else
+ gen = gen_vec_interleave_lowv8si;
+ break;
+ case V4DImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv4di;
+ else
+ gen = gen_vec_interleave_lowv4di;
+ break;
+ case V8SFmode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv8sf;
+ else
+ gen = gen_vec_interleave_lowv8sf;
+ break;
+ case V4DFmode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv4df;
+ else
+ gen = gen_vec_interleave_lowv4df;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ emit_insn (gen (d->target, d->op0, d->op1));
+ return true;
+}
+
/* A subroutine of expand_vec_perm_even_odd_1. Implement the double-word
permutation with two pshufb insns and an ior. We should have already
failed all two instruction sequences. */
@@ -34837,6 +35861,152 @@ expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
return true;
}
+/* Implement arbitrary permutation of one V32QImode and V16QImode operand
+ with two vpshufb insns, vpermq and vpor. We should have already failed
+ all two or three instruction sequences. */
+
+static bool
+expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
+{
+ rtx rperm[2][32], vperm, l, h, hp, op, m128;
+ unsigned int i, nelt, eltsz;
+
+ if (!TARGET_AVX2
+ || d->op0 != d->op1
+ || (d->vmode != V32QImode && d->vmode != V16HImode))
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ nelt = d->nelt;
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+
+ /* Generate two permutation masks. If the required element is within
+ the same lane, it is shuffled in. If the required element from the
+ other lane, force a zero by setting bit 7 in the permutation mask.
+ In the other mask the mask has non-negative elements if element
+ is requested from the other lane, but also moved to the other lane,
+ so that the result of vpshufb can have the two V2TImode halves
+ swapped. */
+ m128 = GEN_INT (-128);
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & (nelt / 2 - 1);
+ unsigned which = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
+
+ for (j = 0; j < eltsz; ++j)
+ {
+ rperm[!!which][(i * eltsz + j) ^ which] = GEN_INT (e * eltsz + j);
+ rperm[!which][(i * eltsz + j) ^ (which ^ 16)] = m128;
+ }
+ }
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
+ vperm = force_reg (V32QImode, vperm);
+
+ h = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
+
+ /* Swap the 128-byte lanes of h into hp. */
+ hp = gen_reg_rtx (V4DImode);
+ op = gen_lowpart (V4DImode, h);
+ emit_insn (gen_avx2_permv4di_1 (hp, op, const2_rtx, GEN_INT (3), const0_rtx,
+ const1_rtx));
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
+ vperm = force_reg (V32QImode, vperm);
+
+ l = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
+
+ op = gen_lowpart (V32QImode, d->target);
+ emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
+
+ return true;
+}
+
+/* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
+ and extract-odd permutations of two V32QImode and V16QImode operand
+ with two vpshufb insns, vpor and vpermq. We should have already
+ failed all two or three instruction sequences. */
+
+static bool
+expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
+{
+ rtx rperm[2][32], vperm, l, h, ior, op, m128;
+ unsigned int i, nelt, eltsz;
+
+ if (!TARGET_AVX2
+ || d->op0 == d->op1
+ || (d->vmode != V32QImode && d->vmode != V16HImode))
+ return false;
+
+ for (i = 0; i < d->nelt; ++i)
+ if ((d->perm[i] ^ (i * 2)) & (3 * d->nelt / 2))
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ nelt = d->nelt;
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+
+ /* Generate two permutation masks. In the first permutation mask
+ the first quarter will contain indexes for the first half
+ of the op0, the second quarter will contain bit 7 set, third quarter
+ will contain indexes for the second half of the op0 and the
+ last quarter bit 7 set. In the second permutation mask
+ the first quarter will contain bit 7 set, the second quarter
+ indexes for the first half of the op1, the third quarter bit 7 set
+ and last quarter indexes for the second half of the op1.
+ I.e. the first mask e.g. for V32QImode extract even will be:
+ 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128
+ (all values masked with 0xf except for -128) and second mask
+ for extract even will be
+ -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe. */
+ m128 = GEN_INT (-128);
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & (nelt / 2 - 1);
+ unsigned which = d->perm[i] >= nelt;
+ unsigned xorv = (i >= nelt / 4 && i < 3 * nelt / 4) ? 24 : 0;
+
+ for (j = 0; j < eltsz; ++j)
+ {
+ rperm[which][(i * eltsz + j) ^ xorv] = GEN_INT (e * eltsz + j);
+ rperm[1 - which][(i * eltsz + j) ^ xorv] = m128;
+ }
+ }
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
+ vperm = force_reg (V32QImode, vperm);
+
+ l = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
+ vperm = force_reg (V32QImode, vperm);
+
+ h = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op1);
+ emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
+
+ ior = gen_reg_rtx (V32QImode);
+ emit_insn (gen_iorv32qi3 (ior, l, h));
+
+ /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
+ op = gen_lowpart (V4DImode, d->target);
+ ior = gen_lowpart (V4DImode, ior);
+ emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+
+ return true;
+}
+
/* A subroutine of ix86_expand_vec_perm_builtin_1. Implement extract-even
and extract-odd permutations. */
@@ -34946,6 +36116,61 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
}
break;
+ case V16HImode:
+ case V32QImode:
+ return expand_vec_perm_vpshufb2_vpermq_even_odd (d);
+
+ case V4DImode:
+ t1 = gen_reg_rtx (V4DImode);
+ t2 = gen_reg_rtx (V4DImode);
+
+ /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
+ emit_insn (gen_avx2_permv2ti (t1, d->op0, d->op1, GEN_INT (0x20)));
+ emit_insn (gen_avx2_permv2ti (t2, d->op0, d->op1, GEN_INT (0x31)));
+
+ /* Now an vpunpck[lh]qdq will produce the result required. */
+ if (odd)
+ t3 = gen_avx2_interleave_highv4di (d->target, t1, t2);
+ else
+ t3 = gen_avx2_interleave_lowv4di (d->target, t1, t2);
+ emit_insn (t3);
+ break;
+
+ case V8SImode:
+ t1 = gen_reg_rtx (V8SImode);
+ t2 = gen_reg_rtx (V8SImode);
+
+ /* Shuffle the lanes around into
+ { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, d->op0),
+ gen_lowpart (V4DImode, d->op1),
+ GEN_INT (0x20)));
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t2),
+ gen_lowpart (V4DImode, d->op0),
+ gen_lowpart (V4DImode, d->op1),
+ GEN_INT (0x31)));
+
+ /* Swap the 2nd and 3rd position in each lane into
+ { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
+ emit_insn (gen_avx2_pshufdv3 (t1, t1,
+ GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
+ emit_insn (gen_avx2_pshufdv3 (t2, t2,
+ GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
+
+ /* Now an vpunpck[lh]qdq will produce
+ { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
+ if (odd)
+ t3 = gen_avx2_interleave_highv4di (gen_lowpart (V4DImode, d->target),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2));
+ else
+ t3 = gen_avx2_interleave_lowv4di (gen_lowpart (V4DImode, d->target),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2));
+ emit_insn (t3);
+ break;
+
default:
gcc_unreachable ();
}
@@ -35026,6 +36251,15 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
gcc_assert (ok);
return true;
+ case V32QImode:
+ case V16HImode:
+ case V8SImode:
+ case V4DImode:
+ /* For AVX2 broadcasts of the first element vpbroadcast* or
+ vpermq should be used by expand_vec_perm_1. */
+ gcc_assert (!TARGET_AVX2 || d->perm[0]);
+ return false;
+
default:
gcc_unreachable ();
}
@@ -35050,6 +36284,117 @@ expand_vec_perm_broadcast (struct expand_vec_perm_d *d)
return expand_vec_perm_broadcast_1 (d);
}
+/* Implement arbitrary permutation of two V32QImode and V16QImode operands
+ with 4 vpshufb insns, 2 vpermq and 3 vpor. We should have already failed
+ all the shorter instruction sequences. */
+
+static bool
+expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
+{
+ rtx rperm[4][32], vperm, l[2], h[2], op, m128;
+ unsigned int i, nelt, eltsz;
+ bool used[4];
+
+ if (!TARGET_AVX2
+ || d->op0 == d->op1
+ || (d->vmode != V32QImode && d->vmode != V16HImode))
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ nelt = d->nelt;
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+
+ /* Generate 4 permutation masks. If the required element is within
+ the same lane, it is shuffled in. If the required element from the
+ other lane, force a zero by setting bit 7 in the permutation mask.
+ In the other mask the mask has non-negative elements if element
+ is requested from the other lane, but also moved to the other lane,
+ so that the result of vpshufb can have the two V2TImode halves
+ swapped. */
+ m128 = GEN_INT (-128);
+ for (i = 0; i < 32; ++i)
+ {
+ rperm[0][i] = m128;
+ rperm[1][i] = m128;
+ rperm[2][i] = m128;
+ rperm[3][i] = m128;
+ }
+ used[0] = false;
+ used[1] = false;
+ used[2] = false;
+ used[3] = false;
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & (nelt / 2 - 1);
+ unsigned xlane = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
+ unsigned int which = ((d->perm[i] & nelt) ? 2 : 0) + (xlane ? 1 : 0);
+
+ for (j = 0; j < eltsz; ++j)
+ rperm[which][(i * eltsz + j) ^ xlane] = GEN_INT (e * eltsz + j);
+ used[which] = true;
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (!used[2 * i + 1])
+ {
+ h[i] = NULL_RTX;
+ continue;
+ }
+ vperm = gen_rtx_CONST_VECTOR (V32QImode,
+ gen_rtvec_v (32, rperm[2 * i + 1]));
+ vperm = force_reg (V32QImode, vperm);
+ h[i] = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (h[i], op, vperm));
+ }
+
+ /* Swap the 128-byte lanes of h[X]. */
+ for (i = 0; i < 2; ++i)
+ {
+ if (h[i] == NULL_RTX)
+ continue;
+ op = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_permv4di_1 (op, gen_lowpart (V4DImode, h[i]),
+ const2_rtx, GEN_INT (3), const0_rtx,
+ const1_rtx));
+ h[i] = gen_lowpart (V32QImode, op);
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (!used[2 * i])
+ {
+ l[i] = NULL_RTX;
+ continue;
+ }
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[2 * i]));
+ vperm = force_reg (V32QImode, vperm);
+ l[i] = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (l[i], op, vperm));
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (h[i] && l[i])
+ {
+ op = gen_reg_rtx (V32QImode);
+ emit_insn (gen_iorv32qi3 (op, l[i], h[i]));
+ l[i] = op;
+ }
+ else if (h[i])
+ l[i] = h[i];
+ }
+
+ gcc_assert (l[0] && l[1]);
+ op = gen_lowpart (V32QImode, d->target);
+ emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
+ return true;
+}
+
/* The guts of ix86_expand_vec_perm_builtin, also used by the ok hook.
With all of the interface bits taken care of, perform the expansion
in D and return true on success. */
@@ -35075,11 +36420,25 @@ ix86_expand_vec_perm_builtin_1 (struct expand_vec_perm_d *d)
if (expand_vec_perm_broadcast (d))
return true;
+ if (expand_vec_perm_vpermq_perm_1 (d))
+ return true;
+
/* Try sequences of three instructions. */
if (expand_vec_perm_pshufb2 (d))
return true;
+ if (expand_vec_perm_interleave3 (d))
+ return true;
+
+ /* Try sequences of four instructions. */
+
+ if (expand_vec_perm_vpshufb2_vpermq (d))
+ return true;
+
+ if (expand_vec_perm_vpshufb2_vpermq_even_odd (d))
+ return true;
+
/* ??? Look for narrow permutations whose element orderings would
allow the promotion to a wider mode. */
@@ -35093,6 +36452,10 @@ ix86_expand_vec_perm_builtin_1 (struct expand_vec_perm_d *d)
if (expand_vec_perm_even_odd (d))
return true;
+ /* Even longer sequences. */
+ if (expand_vec_perm_vpshufb4_vpermq2 (d))
+ return true;
+
return false;
}
@@ -35135,6 +36498,7 @@ ix86_expand_vec_perm_builtin (tree exp)
{
struct expand_vec_perm_d d;
tree arg0, arg1, arg2;
+ bool maybe_retry = false;
arg0 = CALL_EXPR_ARG (exp, 0);
arg1 = CALL_EXPR_ARG (exp, 1);
@@ -35180,6 +36544,7 @@ ix86_expand_vec_perm_builtin (tree exp)
for (i = 0; i < nelt; ++i)
if (d.perm[i] >= nelt)
d.perm[i] -= nelt;
+ maybe_retry = true;
}
/* FALLTHRU */
@@ -35200,6 +36565,28 @@ ix86_expand_vec_perm_builtin (tree exp)
if (ix86_expand_vec_perm_builtin_1 (&d))
return d.target;
+ /* If the mask says both arguments are needed, but they are the same,
+ the above tried to expand with d.op0 == d.op1. If that didn't work,
+ retry with d.op0 != d.op1 as that is what testing has been done with. */
+ if (maybe_retry)
+ {
+ rtx seq;
+ bool ok;
+
+ extract_vec_perm_cst (&d, arg2);
+ d.op1 = gen_reg_rtx (d.vmode);
+ start_sequence ();
+ ok = ix86_expand_vec_perm_builtin_1 (&d);
+ seq = get_insns ();
+ end_sequence ();
+ if (ok)
+ {
+ emit_move_insn (d.op1, d.op0);
+ emit_insn (seq);
+ return d.target;
+ }
+ }
+
/* For compiler generated permutations, we should never got here, because
the compiler should also be checking the ok hook. But since this is a
builtin the user has access too, so don't abort. */
@@ -35225,6 +36612,19 @@ ix86_expand_vec_perm_builtin (tree exp)
d.perm[8], d.perm[9], d.perm[10], d.perm[11],
d.perm[12], d.perm[13], d.perm[14], d.perm[15]);
break;
+ case 32:
+ sorry ("vector permutation "
+ "(%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
+ "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)",
+ d.perm[0], d.perm[1], d.perm[2], d.perm[3],
+ d.perm[4], d.perm[5], d.perm[6], d.perm[7],
+ d.perm[8], d.perm[9], d.perm[10], d.perm[11],
+ d.perm[12], d.perm[13], d.perm[14], d.perm[15],
+ d.perm[16], d.perm[17], d.perm[18], d.perm[19],
+ d.perm[20], d.perm[21], d.perm[22], d.perm[23],
+ d.perm[24], d.perm[25], d.perm[26], d.perm[27],
+ d.perm[28], d.perm[29], d.perm[30], d.perm[31]);
+ break;
default:
gcc_unreachable ();
}
@@ -35232,6 +36632,95 @@ ix86_expand_vec_perm_builtin (tree exp)
return CONST0_RTX (d.vmode);
}
+bool
+ix86_expand_vec_perm_const (rtx operands[4])
+{
+ struct expand_vec_perm_d d;
+ unsigned char perm[MAX_VECT_LEN];
+ int i, nelt, which;
+ rtx sel;
+
+ d.target = operands[0];
+ d.op0 = operands[1];
+ d.op1 = operands[2];
+ sel = operands[3];
+
+ d.vmode = GET_MODE (d.target);
+ gcc_assert (VECTOR_MODE_P (d.vmode));
+ d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
+ d.testing_p = false;
+
+ gcc_assert (GET_CODE (sel) == CONST_VECTOR);
+ gcc_assert (XVECLEN (sel, 0) == nelt);
+ gcc_checking_assert (sizeof (d.perm) == sizeof (perm));
+
+ for (i = which = 0; i < nelt; ++i)
+ {
+ rtx e = XVECEXP (sel, 0, i);
+ int ei = INTVAL (e) & (2 * nelt - 1);
+
+ which |= (ei < nelt ? 1 : 2);
+ d.perm[i] = ei;
+ perm[i] = ei;
+ }
+
+ switch (which)
+ {
+ default:
+ gcc_unreachable();
+
+ case 3:
+ if (!rtx_equal_p (d.op0, d.op1))
+ break;
+
+ /* The elements of PERM do not suggest that only the first operand
+ is used, but both operands are identical. Allow easier matching
+ of the permutation by folding the permutation into the single
+ input vector. */
+ for (i = 0; i < nelt; ++i)
+ if (d.perm[i] >= nelt)
+ d.perm[i] -= nelt;
+ /* FALLTHRU */
+
+ case 1:
+ d.op1 = d.op0;
+ break;
+
+ case 2:
+ for (i = 0; i < nelt; ++i)
+ d.perm[i] -= nelt;
+ d.op0 = d.op1;
+ break;
+ }
+
+ if (ix86_expand_vec_perm_builtin_1 (&d))
+ return true;
+
+ /* If the mask says both arguments are needed, but they are the same,
+ the above tried to expand with d.op0 == d.op1. If that didn't work,
+ retry with d.op0 != d.op1 as that is what testing has been done with. */
+ if (which == 3 && d.op0 == d.op1)
+ {
+ rtx seq;
+ bool ok;
+
+ memcpy (d.perm, perm, sizeof (perm));
+ d.op1 = gen_reg_rtx (d.vmode);
+ start_sequence ();
+ ok = ix86_expand_vec_perm_builtin_1 (&d);
+ seq = get_insns ();
+ end_sequence ();
+ if (ok)
+ {
+ emit_move_insn (d.op1, d.op0);
+ emit_insn (seq);
+ return true;
+ }
+ }
+
+ return false;
+}
+
/* Implement targetm.vectorize.builtin_vec_perm_ok. */
static bool
@@ -35262,10 +36751,10 @@ ix86_vectorize_builtin_vec_perm_ok (tree vec_type, tree mask)
vec_mask = extract_vec_perm_cst (&d, mask);
- /* This hook is cannot be called in response to something that the
- user does (unlike the builtin expander) so we shouldn't ever see
- an error generated from the extract. */
- gcc_assert (vec_mask > 0 && vec_mask <= 3);
+ /* Check whether the mask can be applied to the vector type. */
+ if (vec_mask < 0 || vec_mask > 3)
+ return false;
+
one_vec = (vec_mask != 3);
/* Implementable with shufps or pshufd. */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 7d6e05827b0..bd69ec2b5e3 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2315,6 +2315,19 @@ extern void debug_dispatch_window (int);
((FLAGS) & (IX86_CALLCVT_CDECL | IX86_CALLCVT_STDCALL \
| IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL))
+#define RECIP_MASK_NONE 0x00
+#define RECIP_MASK_DIV 0x01
+#define RECIP_MASK_SQRT 0x02
+#define RECIP_MASK_VEC_DIV 0x04
+#define RECIP_MASK_VEC_SQRT 0x08
+#define RECIP_MASK_ALL (RECIP_MASK_DIV | RECIP_MASK_SQRT \
+ | RECIP_MASK_VEC_DIV | RECIP_MASK_VEC_SQRT)
+
+#define TARGET_RECIP_DIV ((recip_mask & RECIP_MASK_DIV) != 0)
+#define TARGET_RECIP_SQRT ((recip_mask & RECIP_MASK_SQRT) != 0)
+#define TARGET_RECIP_VEC_DIV ((recip_mask & RECIP_MASK_VEC_DIV) != 0)
+#define TARGET_RECIP_VEC_SQRT ((recip_mask & RECIP_MASK_VEC_SQRT) != 0)
+
/*
Local variables:
version-control: t
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 0f6de893832..9c9508d278a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -235,7 +235,6 @@
UNSPEC_VPERMSI
UNSPEC_VPERMDF
UNSPEC_VPERMSF
- UNSPEC_VPERMDI
UNSPEC_VPERMTI
UNSPEC_GATHER
@@ -7062,7 +7061,9 @@
"(TARGET_80387 && X87_ENABLE_ARITH (SFmode))
|| TARGET_SSE_MATH"
{
- if (TARGET_SSE_MATH && TARGET_RECIP && optimize_insn_for_speed_p ()
+ if (TARGET_SSE_MATH
+ && TARGET_RECIP_DIV
+ && optimize_insn_for_speed_p ()
&& flag_finite_math_only && !flag_trapping_math
&& flag_unsafe_math_optimizations)
{
@@ -11695,19 +11696,35 @@
;; See comments for ix86_can_use_return_insn_p in i386.c.
(define_expand "return"
- [(return)]
+ [(simple_return)]
"ix86_can_use_return_insn_p ()"
{
if (crtl->args.pops_args)
{
rtx popc = GEN_INT (crtl->args.pops_args);
- emit_jump_insn (gen_return_pop_internal (popc));
+ emit_jump_insn (gen_simple_return_pop_internal (popc));
DONE;
}
})
-(define_insn "return_internal"
- [(return)]
+;; We need to disable this for TARGET_SEH, as otherwise
+;; shrink-wrapped prologue gets enabled too. This might exceed
+;; the maximum size of prologue in unwind information.
+
+(define_expand "simple_return"
+ [(simple_return)]
+ "!TARGET_SEH"
+{
+ if (crtl->args.pops_args)
+ {
+ rtx popc = GEN_INT (crtl->args.pops_args);
+ emit_jump_insn (gen_simple_return_pop_internal (popc));
+ DONE;
+ }
+})
+
+(define_insn "simple_return_internal"
+ [(simple_return)]
"reload_completed"
"ret"
[(set_attr "length" "1")
@@ -11718,8 +11735,8 @@
;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
;; instruction Athlon and K8 have.
-(define_insn "return_internal_long"
- [(return)
+(define_insn "simple_return_internal_long"
+ [(simple_return)
(unspec [(const_int 0)] UNSPEC_REP)]
"reload_completed"
"rep\;ret"
@@ -11729,8 +11746,8 @@
(set_attr "prefix_rep" "1")
(set_attr "modrm" "0")])
-(define_insn "return_pop_internal"
- [(return)
+(define_insn "simple_return_pop_internal"
+ [(simple_return)
(use (match_operand:SI 0 "const_int_operand" ""))]
"reload_completed"
"ret\t%0"
@@ -11739,8 +11756,8 @@
(set_attr "length_immediate" "2")
(set_attr "modrm" "0")])
-(define_insn "return_indirect_internal"
- [(return)
+(define_insn "simple_return_indirect_internal"
+ [(simple_return)
(use (match_operand:SI 0 "register_operand" "r"))]
"reload_completed"
"jmp\t%A0"
@@ -13426,7 +13443,9 @@
|| (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
{
if (<MODE>mode == SFmode
- && TARGET_SSE_MATH && TARGET_RECIP && !optimize_function_for_size_p (cfun)
+ && TARGET_SSE_MATH
+ && TARGET_RECIP_SQRT
+ && !optimize_function_for_size_p (cfun)
&& flag_finite_math_only && !flag_trapping_math
&& flag_unsafe_math_optimizations)
{
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 8e4d51b3f9f..43009a3c2a6 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -31,6 +31,15 @@ HOST_WIDE_INT ix86_isa_flags = TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_ISA_DEFAU
Variable
HOST_WIDE_INT ix86_isa_flags_explicit
+TargetVariable
+int recip_mask
+
+Variable
+int recip_mask_explicit
+
+TargetSave
+int x_recip_mask_explicit
+
;; Definitions to add to the cl_target_option structure
;; -march= processor
TargetSave
@@ -373,6 +382,10 @@ mrecip
Target Report Mask(RECIP) Save
Generate reciprocals instead of divss and sqrtss.
+mrecip=
+Target Report RejectNegative Joined Var(ix86_recip_name)
+Control generation of reciprocal estimates.
+
mcld
Target Report Mask(CLD) Save
Generate cld instruction in the function prologue.
diff --git a/gcc/config/i386/mingw-w64.h b/gcc/config/i386/mingw-w64.h
index 62a72ef2b92..a45ce28b282 100644
--- a/gcc/config/i386/mingw-w64.h
+++ b/gcc/config/i386/mingw-w64.h
@@ -25,8 +25,8 @@ along with GCC; see the file COPYING3. If not see
#undef CPP_SPEC
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} " \
"%{municode:-DUNICODE} " \
- "%{" SPEC_PTHREAD1 ":-D_REENTRANCE} " \
- "%{" SPEC_PTHREAD2 ":-U_REENTRANCE} "
+ "%{" SPEC_PTHREAD1 ":-D_REENTRANT} " \
+ "%{" SPEC_PTHREAD2 ":-U_REENTRANT} "
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index 7cb280eda32..d9f10c834af 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -78,16 +78,12 @@ along with GCC; see the file COPYING3. If not see
#define SUB_LINK_ENTRY SUB_LINK_ENTRY32
#endif
-/* Override the standard choice of /usr/include as the default prefix
- to try when searching for header files. */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/mingw/include"
-#undef STANDARD_INCLUDE_COMPONENT
-#define STANDARD_INCLUDE_COMPONENT "MINGW"
+#undef NATIVE_SYSTEM_HEADER_COMPONENT
+#define NATIVE_SYSTEM_HEADER_COMPONENT "MINGW"
#undef CPP_SPEC
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} " \
- "%{" SPEC_PTHREAD1 ":-D_REENTRANCE} " \
+ "%{" SPEC_PTHREAD1 ":-D_REENTRANT} " \
"%{" SPEC_PTHREAD2 ": } "
/* For Windows applications, include more libraries, but always include
@@ -235,4 +231,3 @@ do { \
/* We should find a way to not have to update this manually. */
#define LIBGCJ_SONAME "libgcj" /*LIBGCC_EH_EXTN*/ "-12.dll"
-
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 89cc8a75b55..349f5b0c427 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1210,3 +1210,12 @@
return false;
return true;
})
+
+;; Return true if OP is a proper third operand to vpblendw256.
+(define_predicate "avx2_pblendw_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT val = INTVAL (op);
+ HOST_WIDE_INT low = val & 0xff;
+ return val == ((low << 8) | low);
+})
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index baa22a6bc04..ff77003fa61 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -18,13 +18,13 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
-;; All vector modes including V1TImode, used in move patterns.
+;; All vector modes including V?TImode, used in move patterns.
(define_mode_iterator V16
[(V32QI "TARGET_AVX") V16QI
(V16HI "TARGET_AVX") V8HI
(V8SI "TARGET_AVX") V4SI
(V4DI "TARGET_AVX") V2DI
- V1TI
+ (V2TI "TARGET_AVX") V1TI
(V8SF "TARGET_AVX") V4SF
(V4DF "TARGET_AVX") V2DF])
@@ -99,11 +99,13 @@
(define_mode_iterator VI8_AVX2
[(V4DI "TARGET_AVX2") V2DI])
+;; ??? We should probably use TImode instead.
(define_mode_iterator VIMAX_AVX2
[(V2TI "TARGET_AVX2") V1TI])
+;; ??? This should probably be dropped in favor of VIMAX_AVX2.
(define_mode_iterator SSESCALARMODE
- [(V4DI "TARGET_AVX2") TI])
+ [(V2TI "TARGET_AVX2") TI])
(define_mode_iterator VI12_AVX2
[(V32QI "TARGET_AVX2") V16QI
@@ -147,7 +149,7 @@
(V8HI "ssse3") (V16HI "avx2")
(V4SI "ssse3") (V8SI "avx2")
(V2DI "ssse3") (V4DI "avx2")
- (TI "ssse3")])
+ (TI "ssse3") (V2TI "avx2")])
(define_mode_attr sse4_1_avx2
[(V16QI "sse4_1") (V32QI "avx2")
@@ -161,6 +163,12 @@
(V4SI "avx2") (V2DI "avx2")
(V8SI "avx2") (V4DI "avx2")])
+(define_mode_attr vec_avx2
+ [(V16QI "vec") (V32QI "avx2")
+ (V8HI "vec") (V16HI "avx2")
+ (V4SI "vec") (V8SI "avx2")
+ (V2DI "vec") (V4DI "avx2")])
+
;; Mapping of logic-shift operators
(define_code_iterator lshift [lshiftrt ashift])
@@ -236,7 +244,10 @@
(V4SF "V4SI") (V2DF "V2DI")
(V4DF "V4DI") (V8SF "V8SI")
(V8SI "V8SI") (V4DI "V4DI")
- (V4SI "V4SI") (V2DI "V2DI")])
+ (V4SI "V4SI") (V2DI "V2DI")
+ (V16HI "V16HI") (V8HI "V8HI")
+ (V32QI "V32QI") (V16QI "V16QI")
+ ])
;; Mapping of vector modes to a vector mode of double size
(define_mode_attr ssedoublevecmode
@@ -773,7 +784,9 @@
{
ix86_fixup_binary_operands_no_copy (DIV, <MODE>mode, operands);
- if (TARGET_SSE_MATH && TARGET_RECIP && !optimize_insn_for_size_p ()
+ if (TARGET_SSE_MATH
+ && TARGET_RECIP_VEC_DIV
+ && !optimize_insn_for_size_p ()
&& flag_finite_math_only && !flag_trapping_math
&& flag_unsafe_math_optimizations)
{
@@ -851,7 +864,9 @@
(sqrt:VF1 (match_operand:VF1 1 "nonimmediate_operand" "")))]
"TARGET_SSE"
{
- if (TARGET_SSE_MATH && TARGET_RECIP && !optimize_insn_for_size_p ()
+ if (TARGET_SSE_MATH
+ && TARGET_RECIP_VEC_SQRT
+ && !optimize_insn_for_size_p ()
&& flag_finite_math_only && !flag_trapping_math
&& flag_unsafe_math_optimizations)
{
@@ -1288,6 +1303,16 @@
DONE;
})
+(define_expand "reduc_umin_v8hi"
+ [(umin:V8HI
+ (match_operand:V8HI 0 "register_operand" "")
+ (match_operand:V8HI 1 "register_operand" ""))]
+ "TARGET_SSE4_1"
+{
+ ix86_expand_reduc (gen_uminv8hi3, operands[0], operands[1]);
+ DONE;
+})
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel floating point comparisons
@@ -2000,7 +2025,7 @@
"TARGET_FMA"
"@
vfnmsub132<ssemodesuffix>\t{%2, %3, %0|%0, %3, %2}
- vfnmsub231<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
+ vfnmsub213<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
vfnmsub231<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
@@ -2492,7 +2517,7 @@
(set_attr "prefix" "vex")
(set_attr "mode" "V4DF")])
-(define_insn "*avx_cvtdq2pd256_2"
+(define_insn "avx_cvtdq2pd256_2"
[(set (match_operand:V4DF 0 "register_operand" "=x")
(float:V4DF
(vec_select:V4SI
@@ -2761,51 +2786,58 @@
(const_int 2) (const_int 3)]))))]
"TARGET_AVX")
-(define_expand "vec_unpacks_float_hi_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_mode_attr sseunpackfltmode
+ [(V8HI "V4SF") (V4SI "V2DF") (V16HI "V8SF") (V8SI "V4DF")])
+
+(define_expand "vec_unpacks_float_hi_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacks_hi_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
-(define_expand "vec_unpacks_float_lo_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacks_float_lo_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacks_lo_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
-(define_expand "vec_unpacku_float_hi_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacku_float_hi_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacku_hi_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
-(define_expand "vec_unpacku_float_lo_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacku_float_lo_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacku_lo_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
@@ -2917,6 +2949,58 @@
operands[i] = gen_reg_rtx (V2DFmode);
})
+(define_expand "vec_unpacku_float_hi_v8si"
+ [(match_operand:V4DF 0 "register_operand" "")
+ (match_operand:V8SI 1 "register_operand" "")]
+ "TARGET_AVX"
+{
+ REAL_VALUE_TYPE TWO32r;
+ rtx x, tmp[6];
+ int i;
+
+ real_ldexp (&TWO32r, &dconst1, 32);
+ x = const_double_from_real_value (TWO32r, DFmode);
+
+ tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
+ tmp[1] = force_reg (V4DFmode, ix86_build_const_vector (V4DFmode, 1, x));
+ tmp[5] = gen_reg_rtx (V4SImode);
+
+ for (i = 2; i < 5; i++)
+ tmp[i] = gen_reg_rtx (V4DFmode);
+ emit_insn (gen_vec_extract_hi_v8si (tmp[5], operands[1]));
+ emit_insn (gen_avx_cvtdq2pd256 (tmp[2], tmp[5]));
+ emit_insn (gen_rtx_SET (VOIDmode, tmp[3],
+ gen_rtx_LT (V4DFmode, tmp[2], tmp[0])));
+ emit_insn (gen_andv4df3 (tmp[4], tmp[3], tmp[1]));
+ emit_insn (gen_addv4df3 (operands[0], tmp[2], tmp[4]));
+ DONE;
+})
+
+(define_expand "vec_unpacku_float_lo_v8si"
+ [(match_operand:V4DF 0 "register_operand" "")
+ (match_operand:V8SI 1 "nonimmediate_operand" "")]
+ "TARGET_AVX"
+{
+ REAL_VALUE_TYPE TWO32r;
+ rtx x, tmp[5];
+ int i;
+
+ real_ldexp (&TWO32r, &dconst1, 32);
+ x = const_double_from_real_value (TWO32r, DFmode);
+
+ tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
+ tmp[1] = force_reg (V4DFmode, ix86_build_const_vector (V4DFmode, 1, x));
+
+ for (i = 2; i < 5; i++)
+ tmp[i] = gen_reg_rtx (V4DFmode);
+ emit_insn (gen_avx_cvtdq2pd256_2 (tmp[2], operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, tmp[3],
+ gen_rtx_LT (V4DFmode, tmp[2], tmp[0])));
+ emit_insn (gen_andv4df3 (tmp[4], tmp[3], tmp[1]));
+ emit_insn (gen_addv4df3 (operands[0], tmp[2], tmp[4]));
+ DONE;
+})
+
(define_expand "vec_pack_trunc_v4df"
[(set (match_dup 3)
(float_truncate:V4SF
@@ -3761,7 +3845,7 @@
})
(define_expand "vec_set<mode>"
- [(match_operand:V_128 0 "register_operand" "")
+ [(match_operand:V 0 "register_operand" "")
(match_operand:<ssescalarmode> 1 "register_operand" "")
(match_operand 2 "const_int_operand" "")]
"TARGET_SSE"
@@ -4321,10 +4405,10 @@
;; Modes handled by vec_extract_even/odd pattern.
(define_mode_iterator VEC_EXTRACT_EVENODD_MODE
- [(V16QI "TARGET_SSE2")
- (V8HI "TARGET_SSE2")
- (V4SI "TARGET_SSE2")
- (V2DI "TARGET_SSE2")
+ [(V32QI "TARGET_AVX2") (V16QI "TARGET_SSE2")
+ (V16HI "TARGET_AVX2") (V8HI "TARGET_SSE2")
+ (V8SI "TARGET_AVX2") (V4SI "TARGET_SSE2")
+ (V4DI "TARGET_AVX2") (V2DI "TARGET_SSE2")
(V8SF "TARGET_AVX") V4SF
(V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
@@ -4776,10 +4860,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_expand "neg<mode>2"
- [(set (match_operand:VI_128 0 "register_operand" "")
- (minus:VI_128
+ [(set (match_operand:VI_AVX2 0 "register_operand" "")
+ (minus:VI_AVX2
(match_dup 2)
- (match_operand:VI_128 1 "nonimmediate_operand" "")))]
+ (match_operand:VI_AVX2 1 "nonimmediate_operand" "")))]
"TARGET_SSE2"
"operands[2] = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));")
@@ -4829,10 +4913,10 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
-(define_insn_and_split "mulv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "")
- (mult:V16QI (match_operand:V16QI 1 "register_operand" "")
- (match_operand:V16QI 2 "register_operand" "")))]
+(define_insn_and_split "mul<mode>3"
+ [(set (match_operand:VI1_AVX2 0 "register_operand" "")
+ (mult:VI1_AVX2 (match_operand:VI1_AVX2 1 "register_operand" "")
+ (match_operand:VI1_AVX2 2 "register_operand" "")))]
"TARGET_SSE2
&& can_create_pseudo_p ()"
"#"
@@ -4841,34 +4925,41 @@
{
rtx t[6];
int i;
+ enum machine_mode mulmode = <sseunpackmode>mode;
for (i = 0; i < 6; ++i)
- t[i] = gen_reg_rtx (V16QImode);
+ t[i] = gen_reg_rtx (<MODE>mode);
/* Unpack data such that we've got a source byte in each low byte of
each word. We don't care what goes into the high byte of each word.
Rather than trying to get zero in there, most convenient is to let
it be a copy of the low byte. */
- emit_insn (gen_vec_interleave_highv16qi (t[0], operands[1], operands[1]));
- emit_insn (gen_vec_interleave_highv16qi (t[1], operands[2], operands[2]));
- emit_insn (gen_vec_interleave_lowv16qi (t[2], operands[1], operands[1]));
- emit_insn (gen_vec_interleave_lowv16qi (t[3], operands[2], operands[2]));
+ emit_insn (gen_<vec_avx2>_interleave_high<mode> (t[0], operands[1],
+ operands[1]));
+ emit_insn (gen_<vec_avx2>_interleave_high<mode> (t[1], operands[2],
+ operands[2]));
+ emit_insn (gen_<vec_avx2>_interleave_low<mode> (t[2], operands[1],
+ operands[1]));
+ emit_insn (gen_<vec_avx2>_interleave_low<mode> (t[3], operands[2],
+ operands[2]));
/* Multiply words. The end-of-line annotations here give a picture of what
the output of that instruction looks like. Dot means don't care; the
letters are the bytes of the result with A being the most significant. */
- emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[4]), /* .A.B.C.D.E.F.G.H */
- gen_lowpart (V8HImode, t[0]),
- gen_lowpart (V8HImode, t[1])));
- emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[5]), /* .I.J.K.L.M.N.O.P */
- gen_lowpart (V8HImode, t[2]),
- gen_lowpart (V8HImode, t[3])));
+ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (mulmode, t[4]),
+ gen_rtx_MULT (mulmode, /* .A.B.C.D.E.F.G.H */
+ gen_lowpart (mulmode, t[0]),
+ gen_lowpart (mulmode, t[1]))));
+ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (mulmode, t[5]),
+ gen_rtx_MULT (mulmode, /* .I.J.K.L.M.N.O.P */
+ gen_lowpart (mulmode, t[2]),
+ gen_lowpart (mulmode, t[3]))));
/* Extract the even bytes and merge them back together. */
ix86_expand_vec_extract_even_odd (operands[0], t[5], t[4], 0);
set_unique_reg_note (get_last_insn (), REG_EQUAL,
- gen_rtx_MULT (V16QImode, operands[1], operands[2]));
+ gen_rtx_MULT (<MODE>mode, operands[1], operands[2]));
DONE;
})
@@ -5328,10 +5419,10 @@
DONE;
})
-(define_insn_and_split "mulv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "")
- (mult:V2DI (match_operand:V2DI 1 "register_operand" "")
- (match_operand:V2DI 2 "register_operand" "")))]
+(define_insn_and_split "mul<mode>3"
+ [(set (match_operand:VI8_AVX2 0 "register_operand" "")
+ (mult:VI8_AVX2 (match_operand:VI8_AVX2 1 "register_operand" "")
+ (match_operand:VI8_AVX2 2 "register_operand" "")))]
"TARGET_SSE2
&& can_create_pseudo_p ()"
"#"
@@ -5345,7 +5436,7 @@
op1 = operands[1];
op2 = operands[2];
- if (TARGET_XOP)
+ if (TARGET_XOP && <MODE>mode == V2DImode)
{
/* op1: A,B,C,D, op2: E,F,G,H */
op1 = gen_lowpart (V4SImode, op1);
@@ -5377,119 +5468,136 @@
}
else
{
- t1 = gen_reg_rtx (V2DImode);
- t2 = gen_reg_rtx (V2DImode);
- t3 = gen_reg_rtx (V2DImode);
- t4 = gen_reg_rtx (V2DImode);
- t5 = gen_reg_rtx (V2DImode);
- t6 = gen_reg_rtx (V2DImode);
+ t1 = gen_reg_rtx (<MODE>mode);
+ t2 = gen_reg_rtx (<MODE>mode);
+ t3 = gen_reg_rtx (<MODE>mode);
+ t4 = gen_reg_rtx (<MODE>mode);
+ t5 = gen_reg_rtx (<MODE>mode);
+ t6 = gen_reg_rtx (<MODE>mode);
thirtytwo = GEN_INT (32);
/* Multiply low parts. */
- emit_insn (gen_sse2_umulv2siv2di3 (t1, gen_lowpart (V4SImode, op1),
- gen_lowpart (V4SImode, op2)));
+ emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+ (t1, gen_lowpart (<ssepackmode>mode, op1),
+ gen_lowpart (<ssepackmode>mode, op2)));
- /* Shift input vectors left 32 bits so we can multiply high parts. */
- emit_insn (gen_lshrv2di3 (t2, op1, thirtytwo));
- emit_insn (gen_lshrv2di3 (t3, op2, thirtytwo));
+ /* Shift input vectors right 32 bits so we can multiply high parts. */
+ emit_insn (gen_lshr<mode>3 (t2, op1, thirtytwo));
+ emit_insn (gen_lshr<mode>3 (t3, op2, thirtytwo));
/* Multiply high parts by low parts. */
- emit_insn (gen_sse2_umulv2siv2di3 (t4, gen_lowpart (V4SImode, op1),
- gen_lowpart (V4SImode, t3)));
- emit_insn (gen_sse2_umulv2siv2di3 (t5, gen_lowpart (V4SImode, op2),
- gen_lowpart (V4SImode, t2)));
+ emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+ (t4, gen_lowpart (<ssepackmode>mode, op1),
+ gen_lowpart (<ssepackmode>mode, t3)));
+ emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+ (t5, gen_lowpart (<ssepackmode>mode, op2),
+ gen_lowpart (<ssepackmode>mode, t2)));
/* Shift them back. */
- emit_insn (gen_ashlv2di3 (t4, t4, thirtytwo));
- emit_insn (gen_ashlv2di3 (t5, t5, thirtytwo));
+ emit_insn (gen_ashl<mode>3 (t4, t4, thirtytwo));
+ emit_insn (gen_ashl<mode>3 (t5, t5, thirtytwo));
/* Add the three parts together. */
- emit_insn (gen_addv2di3 (t6, t1, t4));
- emit_insn (gen_addv2di3 (op0, t6, t5));
+ emit_insn (gen_add<mode>3 (t6, t1, t4));
+ emit_insn (gen_add<mode>3 (op0, t6, t5));
}
set_unique_reg_note (get_last_insn (), REG_EQUAL,
- gen_rtx_MULT (V2DImode, operands[1], operands[2]));
+ gen_rtx_MULT (<MODE>mode, operands[1], operands[2]));
DONE;
})
-(define_expand "vec_widen_smult_hi_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
+(define_expand "vec_widen_<s>mult_hi_<mode>"
+ [(match_operand:<sseunpackmode> 0 "register_operand" "")
+ (any_extend:<sseunpackmode>
+ (match_operand:VI2_AVX2 1 "register_operand" ""))
+ (match_operand:VI2_AVX2 2 "register_operand" "")]
"TARGET_SSE2"
{
rtx op1, op2, t1, t2, dest;
op1 = operands[1];
op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ t1 = gen_reg_rtx (<MODE>mode);
+ t2 = gen_reg_rtx (<MODE>mode);
+ dest = gen_lowpart (<MODE>mode, operands[0]);
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_smulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_highv8hi (dest, t1, t2));
+ emit_insn (gen_mul<mode>3 (t1, op1, op2));
+ emit_insn (gen_<s>mul<mode>3_highpart (t2, op1, op2));
+ emit_insn (gen_vec_interleave_high<mode> (dest, t1, t2));
DONE;
})
-(define_expand "vec_widen_smult_lo_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
+(define_expand "vec_widen_<s>mult_lo_<mode>"
+ [(match_operand:<sseunpackmode> 0 "register_operand" "")
+ (any_extend:<sseunpackmode>
+ (match_operand:VI2_AVX2 1 "register_operand" ""))
+ (match_operand:VI2_AVX2 2 "register_operand" "")]
"TARGET_SSE2"
{
rtx op1, op2, t1, t2, dest;
op1 = operands[1];
op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ t1 = gen_reg_rtx (<MODE>mode);
+ t2 = gen_reg_rtx (<MODE>mode);
+ dest = gen_lowpart (<MODE>mode, operands[0]);
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_smulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_lowv8hi (dest, t1, t2));
+ emit_insn (gen_mul<mode>3 (t1, op1, op2));
+ emit_insn (gen_<s>mul<mode>3_highpart (t2, op1, op2));
+ emit_insn (gen_vec_interleave_low<mode> (dest, t1, t2));
DONE;
})
-(define_expand "vec_widen_umult_hi_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
- "TARGET_SSE2"
+(define_expand "vec_widen_<s>mult_hi_v8si"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (any_extend:V4DI (match_operand:V8SI 1 "nonimmediate_operand" ""))
+ (match_operand:V8SI 2 "nonimmediate_operand" "")]
+ "TARGET_AVX2"
{
- rtx op1, op2, t1, t2, dest;
-
- op1 = operands[1];
- op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ rtx t1, t2, t3, t4;
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_umulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_highv8hi (dest, t1, t2));
+ t1 = gen_reg_rtx (V4DImode);
+ t2 = gen_reg_rtx (V4DImode);
+ t3 = gen_reg_rtx (V8SImode);
+ t4 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, operands[1]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, operands[2]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1),
+ GEN_INT (2 + (2 << 2) + (3 << 4) + (3 << 6))));
+ emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2),
+ GEN_INT (2 + (2 << 2) + (3 << 4) + (3 << 6))));
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (operands[0], t3, t4));
DONE;
})
-(define_expand "vec_widen_umult_lo_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
- "TARGET_SSE2"
+(define_expand "vec_widen_<s>mult_lo_v8si"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (any_extend:V4DI (match_operand:V8SI 1 "nonimmediate_operand" ""))
+ (match_operand:V8SI 2 "nonimmediate_operand" "")]
+ "TARGET_AVX2"
{
- rtx op1, op2, t1, t2, dest;
-
- op1 = operands[1];
- op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ rtx t1, t2, t3, t4;
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_umulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_lowv8hi (dest, t1, t2));
+ t1 = gen_reg_rtx (V4DImode);
+ t2 = gen_reg_rtx (V4DImode);
+ t3 = gen_reg_rtx (V8SImode);
+ t4 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, operands[1]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, operands[2]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1),
+ GEN_INT (0 + (0 << 2) + (1 << 4) + (1 << 6))));
+ emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2),
+ GEN_INT (0 + (0 << 2) + (1 << 4) + (1 << 6))));
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (operands[0], t3, t4));
DONE;
})
@@ -5497,24 +5605,28 @@
[(match_operand:V2DI 0 "register_operand" "")
(match_operand:V4SI 1 "register_operand" "")
(match_operand:V4SI 2 "register_operand" "")]
- "TARGET_XOP"
+ "TARGET_SSE4_1"
{
- rtx t1, t2;
+ rtx op1, op2, t1, t2;
+ op1 = operands[1];
+ op2 = operands[2];
t1 = gen_reg_rtx (V4SImode);
t2 = gen_reg_rtx (V4SImode);
- emit_insn (gen_sse2_pshufd_1 (t1, operands[1],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_sse2_pshufd_1 (t2, operands[2],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_xop_mulv2div2di3_high (operands[0], t1, t2));
+ if (TARGET_XOP)
+ {
+ emit_insn (gen_sse2_pshufd_1 (t1, op1, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_sse2_pshufd_1 (t2, op2, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_xop_mulv2div2di3_high (operands[0], t1, t2));
+ DONE;
+ }
+
+ emit_insn (gen_vec_interleave_highv4si (t1, op1, op1));
+ emit_insn (gen_vec_interleave_highv4si (t2, op2, op2));
+ emit_insn (gen_sse4_1_mulv2siv2di3 (operands[0], t1, t2));
DONE;
})
@@ -5522,24 +5634,28 @@
[(match_operand:V2DI 0 "register_operand" "")
(match_operand:V4SI 1 "register_operand" "")
(match_operand:V4SI 2 "register_operand" "")]
- "TARGET_XOP"
+ "TARGET_SSE4_1"
{
- rtx t1, t2;
+ rtx op1, op2, t1, t2;
+ op1 = operands[1];
+ op2 = operands[2];
t1 = gen_reg_rtx (V4SImode);
t2 = gen_reg_rtx (V4SImode);
- emit_insn (gen_sse2_pshufd_1 (t1, operands[1],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_sse2_pshufd_1 (t2, operands[2],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_xop_mulv2div2di3_low (operands[0], t1, t2));
+ if (TARGET_XOP)
+ {
+ emit_insn (gen_sse2_pshufd_1 (t1, op1, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_sse2_pshufd_1 (t2, op2, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_xop_mulv2div2di3_low (operands[0], t1, t2));
+ DONE;
+ }
+
+ emit_insn (gen_vec_interleave_lowv4si (t1, op1, op1));
+ emit_insn (gen_vec_interleave_lowv4si (t2, op2, op2));
+ emit_insn (gen_sse4_1_mulv2siv2di3 (operands[0], t1, t2));
DONE;
})
@@ -5581,30 +5697,35 @@
DONE;
})
-(define_expand "sdot_prodv8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")
- (match_operand:V4SI 3 "register_operand" "")]
+(define_expand "sdot_prod<mode>"
+ [(match_operand:<sseunpackmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")
+ (match_operand:VI2_AVX2 2 "register_operand" "")
+ (match_operand:<sseunpackmode> 3 "register_operand" "")]
"TARGET_SSE2"
{
- rtx t = gen_reg_rtx (V4SImode);
- emit_insn (gen_sse2_pmaddwd (t, operands[1], operands[2]));
- emit_insn (gen_addv4si3 (operands[0], operands[3], t));
+ rtx t = gen_reg_rtx (<sseunpackmode>mode);
+ emit_insn (gen_<sse2_avx2>_pmaddwd (t, operands[1], operands[2]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_PLUS (<sseunpackmode>mode,
+ operands[3], t)));
DONE;
})
-(define_expand "udot_prodv4si"
+(define_code_attr sse2_sse4_1
+ [(zero_extend "sse2") (sign_extend "sse4_1")])
+
+(define_expand "<s>dot_prodv4si"
[(match_operand:V2DI 0 "register_operand" "")
- (match_operand:V4SI 1 "register_operand" "")
+ (any_extend:V2DI (match_operand:V4SI 1 "register_operand" ""))
(match_operand:V4SI 2 "register_operand" "")
(match_operand:V2DI 3 "register_operand" "")]
- "TARGET_SSE2"
+ "<CODE> == ZERO_EXTEND ? TARGET_SSE2 : TARGET_SSE4_1"
{
rtx t1, t2, t3, t4;
t1 = gen_reg_rtx (V2DImode);
- emit_insn (gen_sse2_umulv2siv2di3 (t1, operands[1], operands[2]));
+ emit_insn (gen_<sse2_sse4_1>_<u>mulv2siv2di3 (t1, operands[1], operands[2]));
emit_insn (gen_addv2di3 (t1, t1, operands[3]));
t2 = gen_reg_rtx (V4SImode);
@@ -5617,12 +5738,41 @@
GEN_INT (32)));
t4 = gen_reg_rtx (V2DImode);
- emit_insn (gen_sse2_umulv2siv2di3 (t4, t2, t3));
+ emit_insn (gen_<sse2_sse4_1>_<u>mulv2siv2di3 (t4, t2, t3));
emit_insn (gen_addv2di3 (operands[0], t1, t4));
DONE;
})
+(define_expand "<s>dot_prodv8si"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (any_extend:V4DI (match_operand:V8SI 1 "register_operand" ""))
+ (match_operand:V8SI 2 "register_operand" "")
+ (match_operand:V4DI 3 "register_operand" "")]
+ "TARGET_AVX2"
+{
+ rtx t1, t2, t3, t4;
+
+ t1 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (t1, operands[1], operands[2]));
+ emit_insn (gen_addv4di3 (t1, t1, operands[3]));
+
+ t2 = gen_reg_rtx (V8SImode);
+ t3 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, t2),
+ gen_lowpart (V2TImode, operands[1]),
+ GEN_INT (32)));
+ emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, t3),
+ gen_lowpart (V2TImode, operands[2]),
+ GEN_INT (32)));
+
+ t4 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (t4, t2, t3));
+
+ emit_insn (gen_addv4di3 (operands[0], t1, t4));
+ DONE;
+})
+
(define_insn "ashr<mode>3"
[(set (match_operand:VI24_AVX2 0 "register_operand" "=x,x")
(ashiftrt:VI24_AVX2
@@ -5642,21 +5792,6 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "avx2_lshrqv4di3"
- [(set (match_operand:V4DI 0 "register_operand" "=x")
- (lshiftrt:V4DI
- (match_operand:V4DI 1 "register_operand" "x")
- (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))]
- "TARGET_AVX2"
-{
- operands[2] = GEN_INT (INTVAL (operands[2]) / 8);
- return "vpsrldq\t{%2, %1, %0|%0, %1, %2}";
-}
- [(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
- (set_attr "length_immediate" "1")
- (set_attr "mode" "OI")])
-
(define_insn "lshr<mode>3"
[(set (match_operand:VI248_AVX2 0 "register_operand" "=x,x")
(lshiftrt:VI248_AVX2
@@ -5676,20 +5811,6 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "avx2_lshlqv4di3"
- [(set (match_operand:V4DI 0 "register_operand" "=x")
- (ashift:V4DI (match_operand:V4DI 1 "register_operand" "x")
- (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))]
- "TARGET_AVX2"
-{
- operands[2] = GEN_INT (INTVAL (operands[2]) / 8);
- return "vpslldq\t{%2, %1, %0|%0, %1, %2}";
-}
- [(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
- (set_attr "length_immediate" "1")
- (set_attr "mode" "OI")])
-
(define_insn "avx2_lshl<mode>3"
[(set (match_operand:VI248_256 0 "register_operand" "=x")
(ashift:VI248_256
@@ -5706,9 +5827,9 @@
(set_attr "mode" "OI")])
(define_insn "ashl<mode>3"
- [(set (match_operand:VI248_128 0 "register_operand" "=x,x")
- (ashift:VI248_128
- (match_operand:VI248_128 1 "register_operand" "0,x")
+ [(set (match_operand:VI248_AVX2 0 "register_operand" "=x,x")
+ (ashift:VI248_AVX2
+ (match_operand:VI248_AVX2 1 "register_operand" "0,x")
(match_operand:SI 2 "nonmemory_operand" "xN,xN")))]
"TARGET_SSE2"
"@
@@ -5722,7 +5843,7 @@
(const_string "0")))
(set_attr "prefix_data16" "1,*")
(set_attr "prefix" "orig,vex")
- (set_attr "mode" "TI")])
+ (set_attr "mode" "<sseinsnmode>")])
(define_expand "vec_shl_<mode>"
[(set (match_operand:VI_128 0 "register_operand" "")
@@ -6216,6 +6337,44 @@
DONE;
})
+(define_mode_iterator VEC_PERM_AVX2
+ [V16QI V8HI V4SI V2DI V4SF V2DF
+ (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
+ (V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")
+ (V8SF "TARGET_AVX2") (V4DF "TARGET_AVX2")])
+
+(define_expand "vec_perm<mode>"
+ [(match_operand:VEC_PERM_AVX2 0 "register_operand" "")
+ (match_operand:VEC_PERM_AVX2 1 "register_operand" "")
+ (match_operand:VEC_PERM_AVX2 2 "register_operand" "")
+ (match_operand:<sseintvecmode> 3 "register_operand" "")]
+ "TARGET_SSSE3 || TARGET_AVX || TARGET_XOP"
+{
+ ix86_expand_vec_perm (operands);
+ DONE;
+})
+
+(define_mode_iterator VEC_PERM_CONST
+ [(V4SF "TARGET_SSE") (V4SI "TARGET_SSE")
+ (V2DF "TARGET_SSE") (V2DI "TARGET_SSE")
+ (V16QI "TARGET_SSE2") (V8HI "TARGET_SSE2")
+ (V8SF "TARGET_AVX") (V4DF "TARGET_AVX")
+ (V8SI "TARGET_AVX") (V4DI "TARGET_AVX")
+ (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")])
+
+(define_expand "vec_perm_const<mode>"
+ [(match_operand:VEC_PERM_CONST 0 "register_operand" "")
+ (match_operand:VEC_PERM_CONST 1 "register_operand" "")
+ (match_operand:VEC_PERM_CONST 2 "register_operand" "")
+ (match_operand:<sseintvecmode> 3 "" "")]
+ ""
+{
+ if (ix86_expand_vec_perm_const (operands))
+ DONE;
+ else
+ FAIL;
+})
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel bitwise logical operations
@@ -6432,8 +6591,8 @@
(define_expand "vec_pack_trunc_<mode>"
[(match_operand:<ssepackmode> 0 "register_operand" "")
- (match_operand:VI248_128 1 "register_operand" "")
- (match_operand:VI248_128 2 "register_operand" "")]
+ (match_operand:VI248_AVX2 1 "register_operand" "")
+ (match_operand:VI248_AVX2 2 "register_operand" "")]
"TARGET_SSE2"
{
rtx op1 = gen_lowpart (<ssepackmode>mode, operands[1]);
@@ -6514,8 +6673,7 @@
(const_int 28) (const_int 60)
(const_int 29) (const_int 61)
(const_int 30) (const_int 62)
- (const_int 31) (const_int 63)
- (const_int 32) (const_int 64)])))]
+ (const_int 31) (const_int 63)])))]
"TARGET_AVX2"
"vpunpckhbw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
@@ -6560,7 +6718,6 @@
(const_int 5) (const_int 37)
(const_int 6) (const_int 38)
(const_int 7) (const_int 39)
- (const_int 15) (const_int 47)
(const_int 16) (const_int 48)
(const_int 17) (const_int 49)
(const_int 18) (const_int 50)
@@ -6747,6 +6904,38 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
+(define_expand "vec_interleave_high<mode>"
+ [(match_operand:VI_256 0 "register_operand" "=x")
+ (match_operand:VI_256 1 "register_operand" "x")
+ (match_operand:VI_256 2 "nonimmediate_operand" "xm")]
+ "TARGET_AVX2"
+{
+ rtx t1 = gen_reg_rtx (<MODE>mode);
+ rtx t2 = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
+ emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2]));
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, operands[0]),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2), GEN_INT (1 + (3 << 4))));
+ DONE;
+})
+
+(define_expand "vec_interleave_low<mode>"
+ [(match_operand:VI_256 0 "register_operand" "=x")
+ (match_operand:VI_256 1 "register_operand" "x")
+ (match_operand:VI_256 2 "nonimmediate_operand" "xm")]
+ "TARGET_AVX2"
+{
+ rtx t1 = gen_reg_rtx (<MODE>mode);
+ rtx t2 = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
+ emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2]));
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, operands[0]),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2), GEN_INT (0 + (2 << 4))));
+ DONE;
+})
+
;; Modes handled by pinsr patterns.
(define_mode_iterator PINSR_MODE
[(V16QI "TARGET_SSE4_1") V8HI
@@ -6920,7 +7109,11 @@
GEN_INT ((mask >> 0) & 3),
GEN_INT ((mask >> 2) & 3),
GEN_INT ((mask >> 4) & 3),
- GEN_INT ((mask >> 6) & 3)));
+ GEN_INT ((mask >> 6) & 3),
+ GEN_INT (((mask >> 0) & 3) + 4),
+ GEN_INT (((mask >> 2) & 3) + 4),
+ GEN_INT (((mask >> 4) & 3) + 4),
+ GEN_INT (((mask >> 6) & 3) + 4)));
DONE;
})
@@ -6932,11 +7125,15 @@
(match_operand 3 "const_0_to_3_operand" "")
(match_operand 4 "const_0_to_3_operand" "")
(match_operand 5 "const_0_to_3_operand" "")
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)
- (match_dup 5)])))]
- "TARGET_AVX2"
+ (match_operand 6 "const_4_to_7_operand" "")
+ (match_operand 7 "const_4_to_7_operand" "")
+ (match_operand 8 "const_4_to_7_operand" "")
+ (match_operand 9 "const_4_to_7_operand" "")])))]
+ "TARGET_AVX2
+ && INTVAL (operands[2]) + 4 == INTVAL (operands[6])
+ && INTVAL (operands[3]) + 4 == INTVAL (operands[7])
+ && INTVAL (operands[4]) + 4 == INTVAL (operands[8])
+ && INTVAL (operands[5]) + 4 == INTVAL (operands[9])"
{
int mask = 0;
mask |= INTVAL (operands[2]) << 0;
@@ -7003,7 +7200,11 @@
GEN_INT ((mask >> 0) & 3),
GEN_INT ((mask >> 2) & 3),
GEN_INT ((mask >> 4) & 3),
- GEN_INT ((mask >> 6) & 3)));
+ GEN_INT ((mask >> 6) & 3),
+ GEN_INT (((mask >> 0) & 3) + 8),
+ GEN_INT (((mask >> 2) & 3) + 8),
+ GEN_INT (((mask >> 4) & 3) + 8),
+ GEN_INT (((mask >> 6) & 3) + 8)));
DONE;
})
@@ -7019,15 +7220,19 @@
(const_int 5)
(const_int 6)
(const_int 7)
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)
- (match_dup 5)
+ (match_operand 6 "const_8_to_11_operand" "")
+ (match_operand 7 "const_8_to_11_operand" "")
+ (match_operand 8 "const_8_to_11_operand" "")
+ (match_operand 9 "const_8_to_11_operand" "")
(const_int 12)
(const_int 13)
(const_int 14)
(const_int 15)])))]
- "TARGET_AVX2"
+ "TARGET_AVX2
+ && INTVAL (operands[2]) + 8 == INTVAL (operands[6])
+ && INTVAL (operands[3]) + 8 == INTVAL (operands[7])
+ && INTVAL (operands[4]) + 8 == INTVAL (operands[8])
+ && INTVAL (operands[5]) + 8 == INTVAL (operands[9])"
{
int mask = 0;
mask |= INTVAL (operands[2]) << 0;
@@ -7099,7 +7304,11 @@
GEN_INT (((mask >> 0) & 3) + 4),
GEN_INT (((mask >> 2) & 3) + 4),
GEN_INT (((mask >> 4) & 3) + 4),
- GEN_INT (((mask >> 6) & 3) + 4)));
+ GEN_INT (((mask >> 6) & 3) + 4),
+ GEN_INT (((mask >> 0) & 3) + 12),
+ GEN_INT (((mask >> 2) & 3) + 12),
+ GEN_INT (((mask >> 4) & 3) + 12),
+ GEN_INT (((mask >> 6) & 3) + 12)));
DONE;
})
@@ -7119,11 +7328,15 @@
(const_int 9)
(const_int 10)
(const_int 11)
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)
- (match_dup 5)])))]
- "TARGET_AVX2"
+ (match_operand 6 "const_12_to_15_operand" "")
+ (match_operand 7 "const_12_to_15_operand" "")
+ (match_operand 8 "const_12_to_15_operand" "")
+ (match_operand 9 "const_12_to_15_operand" "")])))]
+ "TARGET_AVX2
+ && INTVAL (operands[2]) + 8 == INTVAL (operands[6])
+ && INTVAL (operands[3]) + 8 == INTVAL (operands[7])
+ && INTVAL (operands[4]) + 8 == INTVAL (operands[8])
+ && INTVAL (operands[5]) + 8 == INTVAL (operands[9])"
{
int mask = 0;
mask |= (INTVAL (operands[2]) - 4) << 0;
@@ -7504,25 +7717,25 @@
(define_expand "vec_unpacks_lo_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, false, false); DONE;")
(define_expand "vec_unpacks_hi_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, false, true); DONE;")
(define_expand "vec_unpacku_lo_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, true, false); DONE;")
(define_expand "vec_unpacku_hi_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, true, true); DONE;")
@@ -9418,11 +9631,11 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "<sse4_1_avx2>_pblendw"
- [(set (match_operand:VI2_AVX2 0 "register_operand" "=x,x")
- (vec_merge:VI2_AVX2
- (match_operand:VI2_AVX2 2 "nonimmediate_operand" "xm,xm")
- (match_operand:VI2_AVX2 1 "register_operand" "0,x")
+(define_insn "sse4_1_pblendw"
+ [(set (match_operand:V8HI 0 "register_operand" "=x,x")
+ (vec_merge:V8HI
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm,xm")
+ (match_operand:V8HI 1 "register_operand" "0,x")
(match_operand:SI 3 "const_0_to_255_operand" "n,n")))]
"TARGET_SSE4_1"
"@
@@ -9433,7 +9646,37 @@
(set_attr "prefix_extra" "1")
(set_attr "length_immediate" "1")
(set_attr "prefix" "orig,vex")
- (set_attr "mode" "<sseinsnmode>")])
+ (set_attr "mode" "TI")])
+
+;; The builtin uses an 8-bit immediate. Expand that.
+(define_expand "avx2_pblendw"
+ [(set (match_operand:V16HI 0 "register_operand" "")
+ (vec_merge:V16HI
+ (match_operand:V16HI 2 "nonimmediate_operand" "")
+ (match_operand:V16HI 1 "register_operand" "")
+ (match_operand:SI 3 "const_0_to_255_operand" "")))]
+ "TARGET_AVX2"
+{
+ HOST_WIDE_INT val = INTVAL (operands[3]) & 0xff;
+ operands[3] = GEN_INT (val << 8 | val);
+})
+
+(define_insn "*avx2_pblendw"
+ [(set (match_operand:V16HI 0 "register_operand" "=x")
+ (vec_merge:V16HI
+ (match_operand:V16HI 2 "nonimmediate_operand" "xm")
+ (match_operand:V16HI 1 "register_operand" "x")
+ (match_operand:SI 3 "avx2_pblendw_operand" "n")))]
+ "TARGET_AVX2"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3]) & 0xff);
+ return "vpblendw\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+}
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
(define_insn "avx2_pblendd<mode>"
[(set (match_operand:VI4_AVX2 0 "register_operand" "=x")
@@ -11497,14 +11740,39 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
-(define_insn "avx2_permv4di"
+(define_expand "avx2_permv4di"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (match_operand:V4DI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_0_to_255_operand" "")]
+ "TARGET_AVX2"
+{
+ int mask = INTVAL (operands[2]);
+ emit_insn (gen_avx2_permv4di_1 (operands[0], operands[1],
+ GEN_INT ((mask >> 0) & 3),
+ GEN_INT ((mask >> 2) & 3),
+ GEN_INT ((mask >> 4) & 3),
+ GEN_INT ((mask >> 6) & 3)));
+ DONE;
+})
+
+(define_insn "avx2_permv4di_1"
[(set (match_operand:V4DI 0 "register_operand" "=x")
- (unspec:V4DI
- [(match_operand:V4DI 1 "register_operand" "xm")
- (match_operand:SI 2 "const_0_to_255_operand" "n")]
- UNSPEC_VPERMDI))]
+ (vec_select:V4DI
+ (match_operand:V4DI 1 "nonimmediate_operand" "xm")
+ (parallel [(match_operand 2 "const_0_to_3_operand" "")
+ (match_operand 3 "const_0_to_3_operand" "")
+ (match_operand 4 "const_0_to_3_operand" "")
+ (match_operand 5 "const_0_to_3_operand" "")])))]
"TARGET_AVX2"
- "vpermq\t{%2, %1, %0|%0, %1, %2}"
+{
+ int mask = 0;
+ mask |= INTVAL (operands[2]) << 0;
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+ return "vpermq\t{%2, %1, %0|%0, %1, %2}";
+}
[(set_attr "type" "sselog")
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
@@ -11513,7 +11781,7 @@
[(set (match_operand:V4DI 0 "register_operand" "=x")
(unspec:V4DI
[(match_operand:V4DI 1 "register_operand" "x")
- (match_operand:V4DI 2 "register_operand" "xm")
+ (match_operand:V4DI 2 "nonimmediate_operand" "xm")
(match_operand:SI 3 "const_0_to_255_operand" "n")]
UNSPEC_VPERMTI))]
"TARGET_AVX2"
@@ -12376,7 +12644,7 @@
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
-(define_insn "*vec_concat<mode>_avx"
+(define_insn "avx_vec_concat<mode>"
[(set (match_operand:V_256 0 "register_operand" "=x,x")
(vec_concat:V_256
(match_operand:<ssehalfvecmode> 1 "register_operand" "x,x")
@@ -12495,55 +12763,61 @@
(V8SI "V8SI") (V8SF "V8SI")])
(define_expand "avx2_gathersi<mode>"
- [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
- (unspec:VEC_GATHER_MODE
- [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
- (match_operand:<ssescalarmode> 2 "memory_operand" "")
- (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "")
- (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
- (match_operand:SI 5 "const1248_operand " "")]
- UNSPEC_GATHER))]
+ [(parallel [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
+ (unspec:VEC_GATHER_MODE
+ [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
+ (match_operand 2 "register_operand" "")
+ (mem:BLK (scratch))
+ (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "")
+ (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
+ (match_operand:SI 5 "const1248_operand " "")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VEC_GATHER_MODE 6 ""))])]
"TARGET_AVX2")
(define_insn "*avx2_gathersi<mode>"
- [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=x")
+ [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=&x")
(unspec:VEC_GATHER_MODE
- [(match_operand:VEC_GATHER_MODE 1 "register_operand" "0")
- (mem:<ssescalarmode>
- (match_operand:P 2 "register_operand" "r"))
- (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "x")
- (match_operand:VEC_GATHER_MODE 4 "register_operand" "x")
- (match_operand:SI 5 "const1248_operand" "n")]
- UNSPEC_GATHER))]
+ [(match_operand:VEC_GATHER_MODE 2 "register_operand" "0")
+ (match_operand:P 3 "register_operand" "r")
+ (mem:BLK (scratch))
+ (match_operand:<VEC_GATHER_MODE> 4 "register_operand" "x")
+ (match_operand:VEC_GATHER_MODE 5 "register_operand" "1")
+ (match_operand:SI 6 "const1248_operand" "n")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VEC_GATHER_MODE 1 "=&x"))]
"TARGET_AVX2"
- "v<gthrfirstp>gatherd<gthrlastp>\t{%4, (%2, %3, %c5), %0|%0, (%2, %3, %c5), %4}"
+ "v<gthrfirstp>gatherd<gthrlastp>\t{%1, (%3, %4, %p6), %0|%0, (%3, %4, %p6), %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
(define_expand "avx2_gatherdi<mode>"
- [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
- (unspec:VEC_GATHER_MODE
- [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
- (match_operand:<ssescalarmode> 2 "memory_operand" "")
- (match_operand:<AVXMODE48P_DI> 3 "register_operand" "")
- (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
- (match_operand:SI 5 "const1248_operand " "")]
- UNSPEC_GATHER))]
+ [(parallel [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
+ (unspec:VEC_GATHER_MODE
+ [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
+ (match_operand 2 "register_operand" "")
+ (mem:BLK (scratch))
+ (match_operand:<AVXMODE48P_DI> 3 "register_operand" "")
+ (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
+ (match_operand:SI 5 "const1248_operand " "")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VEC_GATHER_MODE 6 ""))])]
"TARGET_AVX2")
(define_insn "*avx2_gatherdi<mode>"
- [(set (match_operand:AVXMODE48P_DI 0 "register_operand" "=x")
+ [(set (match_operand:AVXMODE48P_DI 0 "register_operand" "=&x")
(unspec:AVXMODE48P_DI
- [(match_operand:AVXMODE48P_DI 1 "register_operand" "0")
- (mem:<ssescalarmode>
- (match_operand:P 2 "register_operand" "r"))
- (match_operand:<AVXMODE48P_DI> 3 "register_operand" "x")
- (match_operand:AVXMODE48P_DI 4 "register_operand" "x")
- (match_operand:SI 5 "const1248_operand" "n")]
- UNSPEC_GATHER))]
+ [(match_operand:AVXMODE48P_DI 2 "register_operand" "0")
+ (match_operand:P 3 "register_operand" "r")
+ (mem:BLK (scratch))
+ (match_operand:<AVXMODE48P_DI> 4 "register_operand" "x")
+ (match_operand:AVXMODE48P_DI 5 "register_operand" "1")
+ (match_operand:SI 6 "const1248_operand" "n")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:AVXMODE48P_DI 1 "=&x"))]
"TARGET_AVX2"
- "v<gthrfirstp>gatherq<gthrlastp>\t{%4, (%2, %3, %c5), %0|%0, (%2, %3, %c5), %4}"
+ "v<gthrfirstp>gatherq<gthrlastp>\t{%1, (%3, %4, %p6), %0|%0, (%3, %4, %p6), %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
@@ -12551,28 +12825,31 @@
;; Special handling for VEX.256 with float arguments
;; since there're still xmms as operands
(define_expand "avx2_gatherdi<mode>256"
- [(set (match_operand:VI4F_128 0 "register_operand" "")
- (unspec:VI4F_128
- [(match_operand:VI4F_128 1 "register_operand" "")
- (match_operand:<ssescalarmode> 2 "memory_operand" "")
- (match_operand:V4DI 3 "register_operand" "")
- (match_operand:VI4F_128 4 "register_operand" "")
- (match_operand:SI 5 "const1248_operand " "")]
- UNSPEC_GATHER))]
+ [(parallel [(set (match_operand:VI4F_128 0 "register_operand" "")
+ (unspec:VI4F_128
+ [(match_operand:VI4F_128 1 "register_operand" "")
+ (match_operand 2 "register_operand" "")
+ (mem:BLK (scratch))
+ (match_operand:V4DI 3 "register_operand" "")
+ (match_operand:VI4F_128 4 "register_operand" "")
+ (match_operand:SI 5 "const1248_operand " "")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VI4F_128 6 ""))])]
"TARGET_AVX2")
(define_insn "*avx2_gatherdi<mode>256"
[(set (match_operand:VI4F_128 0 "register_operand" "=x")
(unspec:VI4F_128
- [(match_operand:VI4F_128 1 "register_operand" "0")
- (mem:<ssescalarmode>
- (match_operand:P 2 "register_operand" "r"))
- (match_operand:V4DI 3 "register_operand" "x")
- (match_operand:VI4F_128 4 "register_operand" "x")
- (match_operand:SI 5 "const1248_operand" "n")]
- UNSPEC_GATHER))]
+ [(match_operand:VI4F_128 2 "register_operand" "0")
+ (match_operand:P 3 "register_operand" "r")
+ (mem:BLK (scratch))
+ (match_operand:V4DI 4 "register_operand" "x")
+ (match_operand:VI4F_128 5 "register_operand" "1")
+ (match_operand:SI 6 "const1248_operand" "n")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VI4F_128 1 "=&x"))]
"TARGET_AVX2"
- "v<gthrfirstp>gatherq<gthrlastp>\t{%4, (%2, %3, %c5), %0|%0, (%2, %3, %c5), %4}"
+ "v<gthrfirstp>gatherq<gthrlastp>\t{%1, (%3, %4, %p6), %0|%0, (%3, %4, %p6), %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
diff --git a/gcc/config/i386/t-djgpp b/gcc/config/i386/t-djgpp
deleted file mode 100644
index 7b54b7ba7aa..00000000000
--- a/gcc/config/i386/t-djgpp
+++ /dev/null
@@ -1,2 +0,0 @@
-# Location of DJGPP's header directory.
-NATIVE_SYSTEM_HEADER_DIR=$(DJDIR)/include
diff --git a/gcc/config/i386/t-mingw-w32 b/gcc/config/i386/t-mingw-w32
index a1421801664..83cee71f1c1 100644
--- a/gcc/config/i386/t-mingw-w32
+++ b/gcc/config/i386/t-mingw-w32
@@ -1,6 +1,3 @@
-# Match SYSTEM_INCLUDE_DIR
-NATIVE_SYSTEM_HEADER_DIR = /mingw/include
-
MULTILIB_OPTIONS = m64/m32
MULTILIB_DIRNAMES = 64 32
MULTILIB_OSDIRNAMES = ../lib64 ../lib
diff --git a/gcc/config/i386/t-mingw-w64 b/gcc/config/i386/t-mingw-w64
index dbe2d00a2e7..041a02f1018 100644
--- a/gcc/config/i386/t-mingw-w64
+++ b/gcc/config/i386/t-mingw-w64
@@ -1,6 +1,3 @@
-# Match SYSTEM_INCLUDE_DIR
-NATIVE_SYSTEM_HEADER_DIR = /mingw/include
-
MULTILIB_OPTIONS = m64/m32
MULTILIB_DIRNAMES = 64 32
MULTILIB_OSDIRNAMES = ../lib ../lib32
diff --git a/gcc/config/i386/t-mingw32 b/gcc/config/i386/t-mingw32
index a8235242a50..bfdef6723ce 100644
--- a/gcc/config/i386/t-mingw32
+++ b/gcc/config/i386/t-mingw32
@@ -1,5 +1,2 @@
-# Match SYSTEM_INCLUDE_DIR
-NATIVE_SYSTEM_HEADER_DIR = /mingw/include
-
# MinGW-specific parts of LIB_SPEC
SHLIB_LC = -lmingwthrd -lmingw32 -lmingwex -lmoldname -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index f4fbf08396d..1f6fe1e4c10 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -10100,15 +10100,12 @@ ia64_init_builtins (void)
if (TARGET_HPUX)
{
- if (built_in_decls [BUILT_IN_FINITE])
- set_user_assembler_name (built_in_decls [BUILT_IN_FINITE],
- "_Isfinite");
- if (built_in_decls [BUILT_IN_FINITEF])
- set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF],
- "_Isfinitef");
- if (built_in_decls [BUILT_IN_FINITEL])
- set_user_assembler_name (built_in_decls [BUILT_IN_FINITEL],
- "_Isfinitef128");
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITE)) != NULL_TREE)
+ set_user_assembler_name (decl, "_Isfinite");
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITEF)) != NULL_TREE)
+ set_user_assembler_name (decl, "_Isfinitef");
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITEL)) != NULL_TREE)
+ set_user_assembler_name (decl, "_Isfinitef128");
}
}
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index 8017cf25ed0..df1888628cc 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -51,7 +51,6 @@ extern bool strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn,
extern int standard_68881_constant_p (rtx);
extern void print_operand_address (FILE *, rtx);
extern void print_operand (FILE *, rtx, int);
-extern bool m68k_output_addr_const_extra (FILE *, rtx);
extern void notice_update_cc (rtx, rtx);
extern bool m68k_legitimate_base_reg_p (rtx, bool);
extern bool m68k_legitimate_index_reg_p (rtx, bool);
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 71df1410394..e447708d239 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -163,6 +163,7 @@ static void m68k_function_arg_advance (cumulative_args_t, enum machine_mode,
static rtx m68k_function_arg (cumulative_args_t, enum machine_mode,
const_tree, bool);
static bool m68k_cannot_force_const_mem (enum machine_mode mode, rtx x);
+static bool m68k_output_addr_const_extra (FILE *, rtx);
/* Initialize the GCC target structure. */
@@ -297,6 +298,9 @@ static bool m68k_cannot_force_const_mem (enum machine_mode mode, rtx x);
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P m68k_legitimate_constant_p
+#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
+#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA m68k_output_addr_const_extra
+
static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
@@ -4540,9 +4544,9 @@ m68k_get_reloc_decoration (enum m68k_reloc reloc)
}
}
-/* m68k implementation of OUTPUT_ADDR_CONST_EXTRA. */
+/* m68k implementation of TARGET_OUTPUT_ADDR_CONST_EXTRA. */
-bool
+static bool
m68k_output_addr_const_extra (FILE *file, rtx x)
{
if (GET_CODE (x) == UNSPEC)
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index e69e164e71c..c8bd3eee122 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -935,12 +935,6 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
-#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
-do { \
- if (! m68k_output_addr_const_extra (FILE, (X))) \
- goto FAIL; \
-} while (0);
-
#include "config/m68k/m68k-opts.h"
enum fpu_type
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index d0b6b4c2b74..ff72e28a35c 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -9892,6 +9892,14 @@ mips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
mips_end_function_definition (fnname);
}
+/* Emit an optimisation barrier for accesses to the current frame. */
+
+static void
+mips_frame_barrier (void)
+{
+ emit_clobber (gen_frame_mem (BLKmode, stack_pointer_rtx));
+}
+
/* Save register REG to MEM. Make the instruction frame-related. */
static void
@@ -10035,6 +10043,7 @@ mips_expand_prologue (void)
insn = mips16e_build_save_restore (false, &mask, &offset,
nargs, step1);
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
+ mips_frame_barrier ();
size -= step1;
/* Check if we need to save other registers. */
@@ -10075,6 +10084,7 @@ mips_expand_prologue (void)
insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (-step1));
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
+ mips_frame_barrier ();
size -= step1;
/* Start at the uppermost location for saving. */
@@ -10135,6 +10145,7 @@ mips_expand_prologue (void)
stack_pointer_rtx,
GEN_INT (-step1));
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
+ mips_frame_barrier ();
size -= step1;
}
mips_for_each_saved_acc (size, mips_save_reg);
@@ -10175,6 +10186,7 @@ mips_expand_prologue (void)
(gen_rtx_SET (VOIDmode, stack_pointer_rtx,
plus_constant (stack_pointer_rtx, -size)));
}
+ mips_frame_barrier ();
}
/* Set up the frame pointer, if we're using one. */
@@ -10315,6 +10327,35 @@ mips_restore_reg (rtx reg, rtx mem)
mips_epilogue.cfa_restore_sp_offset);
}
+/* Emit code to set the stack pointer to BASE + OFFSET, given that
+ BASE + OFFSET is NEW_FRAME_SIZE bytes below the top of the frame.
+ BASE, if not the stack pointer, is available as a temporary. */
+
+static void
+mips_deallocate_stack (rtx base, rtx offset, HOST_WIDE_INT new_frame_size)
+{
+ if (base == stack_pointer_rtx && offset == const0_rtx)
+ return;
+
+ mips_frame_barrier ();
+ if (offset == const0_rtx)
+ {
+ emit_move_insn (stack_pointer_rtx, base);
+ mips_epilogue_set_cfa (stack_pointer_rtx, new_frame_size);
+ }
+ else if (TARGET_MIPS16 && base != stack_pointer_rtx)
+ {
+ emit_insn (gen_add3_insn (base, base, offset));
+ mips_epilogue_set_cfa (base, new_frame_size);
+ emit_move_insn (stack_pointer_rtx, base);
+ }
+ else
+ {
+ emit_insn (gen_add3_insn (stack_pointer_rtx, base, offset));
+ mips_epilogue_set_cfa (stack_pointer_rtx, new_frame_size);
+ }
+}
+
/* Emit any instructions needed before a return. */
void
@@ -10341,7 +10382,7 @@ mips_expand_epilogue (bool sibcall_p)
{
const struct mips_frame_info *frame;
HOST_WIDE_INT step1, step2;
- rtx base, target, insn;
+ rtx base, adjust, insn;
if (!sibcall_p && mips_can_use_return_insn ())
{
@@ -10384,31 +10425,14 @@ mips_expand_epilogue (bool sibcall_p)
step1 -= step2;
}
- /* Set TARGET to BASE + STEP1. */
- target = base;
- if (step1 > 0)
+ /* Get an rtx for STEP1 that we can add to BASE. */
+ adjust = GEN_INT (step1);
+ if (!SMALL_OPERAND (step1))
{
- rtx adjust;
-
- /* Get an rtx for STEP1 that we can add to BASE. */
- adjust = GEN_INT (step1);
- if (!SMALL_OPERAND (step1))
- {
- mips_emit_move (MIPS_EPILOGUE_TEMP (Pmode), adjust);
- adjust = MIPS_EPILOGUE_TEMP (Pmode);
- }
-
- /* Normal mode code can copy the result straight into $sp. */
- if (!TARGET_MIPS16)
- target = stack_pointer_rtx;
-
- emit_insn (gen_add3_insn (target, base, adjust));
- mips_epilogue_set_cfa (target, step2);
+ mips_emit_move (MIPS_EPILOGUE_TEMP (Pmode), adjust);
+ adjust = MIPS_EPILOGUE_TEMP (Pmode);
}
-
- /* Copy TARGET into the stack pointer. */
- if (target != stack_pointer_rtx)
- mips_emit_move (stack_pointer_rtx, target);
+ mips_deallocate_stack (base, adjust, step2);
/* If we're using addressing macros, $gp is implicitly used by all
SYMBOL_REFs. We must emit a blockage insn before restoring $gp
@@ -10437,6 +10461,7 @@ mips_expand_epilogue (bool sibcall_p)
/* Restore the remaining registers and deallocate the final bit
of the frame. */
+ mips_frame_barrier ();
emit_insn (restore);
mips_epilogue_set_cfa (stack_pointer_rtx, 0);
}
@@ -10473,13 +10498,8 @@ mips_expand_epilogue (bool sibcall_p)
offset -= UNITS_PER_WORD;
/* If we don't use shoadow register set, we need to update SP. */
- if (!cfun->machine->use_shadow_register_set_p && step2 > 0)
- {
- emit_insn (gen_add3_insn (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (step2)));
- mips_epilogue_set_cfa (stack_pointer_rtx, 0);
- }
+ if (!cfun->machine->use_shadow_register_set_p)
+ mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
else
/* The choice of position is somewhat arbitrary in this case. */
mips_epilogue_emit_cfa_restores ();
@@ -10489,16 +10509,8 @@ mips_expand_epilogue (bool sibcall_p)
gen_rtx_REG (SImode, K0_REG_NUM)));
}
else
- {
- /* Deallocate the final bit of the frame. */
- if (step2 > 0)
- {
- emit_insn (gen_add3_insn (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (step2)));
- mips_epilogue_set_cfa (stack_pointer_rtx, 0);
- }
- }
+ /* Deallocate the final bit of the frame. */
+ mips_deallocate_stack (stack_pointer_rtx, GEN_INT (step2), 0);
}
gcc_assert (!mips_epilogue.cfa_restores);
diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md
index b3098b434ed..1b4097ec225 100644
--- a/gcc/config/mips/sync.md
+++ b/gcc/config/mips/sync.md
@@ -136,7 +136,7 @@
[(match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")
(atomic_hiqi_op:SI (match_dup 0)
- (match_operand:SI 3 "register_operand" "dJ"))]
+ (match_operand:SI 3 "reg_or_0_operand" "dJ"))]
UNSPEC_SYNC_OLD_OP_12))
(clobber (match_scratch:SI 4 "=&d"))]
"GENERATE_LL_SC"
@@ -177,7 +177,7 @@
[(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
(atomic_hiqi_op:SI (match_dup 0)
- (match_operand:SI 4 "register_operand" "dJ"))]
+ (match_operand:SI 4 "reg_or_0_operand" "dJ"))]
UNSPEC_SYNC_OLD_OP_12))
(clobber (match_scratch:SI 5 "=&d"))]
"GENERATE_LL_SC"
@@ -218,7 +218,7 @@
(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
(atomic_hiqi_op:SI (match_dup 0)
- (match_operand:SI 4 "register_operand" "dJ"))]
+ (match_operand:SI 4 "reg_or_0_operand" "dJ"))]
UNSPEC_SYNC_NEW_OP_12))
(set (match_dup 1)
(unspec_volatile:SI
@@ -259,7 +259,7 @@
[(match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")
(match_dup 0)
- (match_operand:SI 3 "register_operand" "dJ")]
+ (match_operand:SI 3 "reg_or_0_operand" "dJ")]
UNSPEC_SYNC_OLD_OP_12))
(clobber (match_scratch:SI 4 "=&d"))]
"GENERATE_LL_SC"
@@ -298,7 +298,7 @@
(unspec_volatile:SI
[(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
- (match_operand:SI 4 "register_operand" "dJ")]
+ (match_operand:SI 4 "reg_or_0_operand" "dJ")]
UNSPEC_SYNC_OLD_OP_12))
(clobber (match_scratch:SI 5 "=&d"))]
"GENERATE_LL_SC"
@@ -337,7 +337,7 @@
[(match_operand:SI 1 "memory_operand" "+R")
(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
- (match_operand:SI 4 "register_operand" "dJ")]
+ (match_operand:SI 4 "reg_or_0_operand" "dJ")]
UNSPEC_SYNC_NEW_OP_12))
(set (match_dup 1)
(unspec_volatile:SI
@@ -546,7 +546,7 @@
(set (match_dup 1)
(unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")
- (match_operand:SI 4 "arith_operand" "dJ")]
+ (match_operand:SI 4 "reg_or_0_operand" "dJ")]
UNSPEC_SYNC_EXCHANGE_12))]
"GENERATE_LL_SC"
{ return mips_output_sync_loop (insn, operands); }
diff --git a/gcc/config/openbsd.h b/gcc/config/openbsd.h
index aa279ed4738..fad29154cef 100644
--- a/gcc/config/openbsd.h
+++ b/gcc/config/openbsd.h
@@ -1,5 +1,5 @@
/* Base configuration file for all OpenBSD targets.
- Copyright (C) 1999, 2000, 2004, 2005, 2007, 2009, 2010
+ Copyright (C) 1999, 2000, 2004, 2005, 2007, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -59,7 +59,7 @@ along with GCC; see the file COPYING3. If not see
{ GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \
{ GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1 }, \
{ GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1 }, \
- { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 }, \
+ { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0 }, \
{ 0, 0, 0, 0 } \
}
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index e3ad4c80d89..66e3fc700b4 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -555,16 +555,21 @@ static void
pa_init_builtins (void)
{
#ifdef DONT_HAVE_FPUTC_UNLOCKED
- built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] =
- built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
- implicit_built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED]
- = implicit_built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
+ {
+ tree decl = builtin_decl_explicit (BUILT_IN_PUTC_UNLOCKED);
+ set_builtin_decl (BUILT_IN_FPUTC_UNLOCKED, decl,
+ builtin_decl_implicit_p (BUILT_IN_PUTC_UNLOCKED));
+ }
#endif
#if TARGET_HPUX_11
- if (built_in_decls [BUILT_IN_FINITE])
- set_user_assembler_name (built_in_decls [BUILT_IN_FINITE], "_Isfinite");
- if (built_in_decls [BUILT_IN_FINITEF])
- set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], "_Isfinitef");
+ {
+ tree decl;
+
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITE)) != NULL_TREE)
+ set_user_assembler_name (decl, "_Isfinite");
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITEF)) != NULL_TREE)
+ set_user_assembler_name (decl, "_Isfinitef");
+ }
#endif
if (HPUX_LONG_DOUBLE_LIBRARY)
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index 2c678a3a247..29eabbb6fd8 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -97,6 +97,9 @@
{ \
builtin_define ("_IBMR2"); \
builtin_define ("_POWER"); \
+ builtin_define ("__powerpc__"); \
+ builtin_define ("__PPC__"); \
+ builtin_define ("__unix__"); \
builtin_define ("_AIX"); \
builtin_define ("_AIX32"); \
builtin_define ("_AIX41"); \
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 9e7437ed0fe..84c5444e67d 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -1357,6 +1357,15 @@
"vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
+(define_expand "vec_permv16qi"
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "")
+ (match_operand:V16QI 2 "register_operand" "")
+ (match_operand:V16QI 3 "register_operand" "")]
+ UNSPEC_VPERM))]
+ "TARGET_ALTIVEC"
+ "")
+
(define_insn "altivec_vrfip" ; ceil
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 63c0f0ce201..d97ddd32849 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3739,7 +3739,7 @@ rs6000_builtin_vectorized_libmass (tree fndecl, tree type_out, tree type_in)
case BUILT_IN_SQRT:
case BUILT_IN_TAN:
case BUILT_IN_TANH:
- bdecl = implicit_built_in_decls[fn];
+ bdecl = builtin_decl_implicit (fn);
suffix = "d2"; /* pow -> powd2 */
if (el_mode != DFmode
|| n != 2)
@@ -3776,7 +3776,7 @@ rs6000_builtin_vectorized_libmass (tree fndecl, tree type_out, tree type_in)
case BUILT_IN_SQRTF:
case BUILT_IN_TANF:
case BUILT_IN_TANHF:
- bdecl = implicit_built_in_decls[fn];
+ bdecl = builtin_decl_implicit (fn);
suffix = "4"; /* powf -> powf4 */
if (el_mode != SFmode
|| n != 4)
@@ -4758,7 +4758,7 @@ rs6000_expand_vector_init (rtx target, rtx vals)
/* Store value to stack temp. Load vector element. Splat. However, splat
of 64-bit items is not supported on Altivec. */
- if (all_same && GET_MODE_SIZE (mode) <= 4)
+ if (all_same && GET_MODE_SIZE (inner_mode) <= 4)
{
mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
emit_move_insn (adjust_address_nv (mem, inner_mode, 0),
@@ -9400,7 +9400,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
tree tmp = create_tmp_var (type, "va_arg_tmp");
tree dest_addr = build_fold_addr_expr (tmp);
- tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
3, dest_addr, addr, size_int (rsize * 4));
gimplify_and_add (copy, pre_p);
@@ -12213,8 +12213,8 @@ rs6000_init_builtins (void)
#if TARGET_XCOFF
/* AIX libm provides clog as __clog. */
- if (built_in_decls [BUILT_IN_CLOG])
- set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog");
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
+ set_user_assembler_name (tdecl, "__clog");
#endif
#ifdef SUBTARGET_INIT_BUILTINS
diff --git a/gcc/config/rx/constraints.md b/gcc/config/rx/constraints.md
index 9f7dc9ff816..7822914acbb 100644
--- a/gcc/config/rx/constraints.md
+++ b/gcc/config/rx/constraints.md
@@ -1,5 +1,5 @@
;; Constraint definitions for Renesas RX.
-;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2009, 2010. 2011 Free Software Foundation, Inc.
;; Contributed by Red Hat.
;;
;; This file is part of GCC.
@@ -86,3 +86,23 @@
)
)
)
+
+(define_constraint "Rpid"
+ "A MEM to a PID variable"
+ (and (match_code "mem")
+ (and (match_code "plus" "0")
+ (and (match_code "reg,subreg" "00")
+ (match_code "unspec" "01")
+ )
+ )
+ )
+)
+
+(define_constraint "Rpda"
+ "An address to a PID variable"
+ (and (match_code "plus" "")
+ (and (match_code "reg,subreg" "0")
+ (match_code "unspec" "1")
+ )
+ )
+)
diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h
index 56d69316905..365bf66babd 100644
--- a/gcc/config/rx/rx-protos.h
+++ b/gcc/config/rx/rx-protos.h
@@ -35,6 +35,7 @@ extern bool rx_is_legitimate_constant (enum machine_mode, rtx);
extern bool rx_is_restricted_memory_address (rtx,
enum machine_mode);
extern bool rx_match_ccmode (rtx, enum machine_mode);
+extern rtx rx_maybe_pidify_operand (rtx, int);
extern void rx_notice_update_cc (rtx, rtx);
extern void rx_split_cbranch (enum machine_mode, enum rtx_code,
rtx, rtx, rtx);
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index dcf693a6337..c9720eb3e15 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -51,7 +51,43 @@
#include "target-def.h"
#include "langhooks.h"
#include "opts.h"
+
+static unsigned int rx_gp_base_regnum_val = INVALID_REGNUM;
+static unsigned int rx_pid_base_regnum_val = INVALID_REGNUM;
+static unsigned int rx_num_interrupt_regs;
+static unsigned int
+rx_gp_base_regnum (void)
+{
+ if (rx_gp_base_regnum_val == INVALID_REGNUM)
+ gcc_unreachable ();
+ return rx_gp_base_regnum_val;
+}
+
+static unsigned int
+rx_pid_base_regnum (void)
+{
+ if (rx_pid_base_regnum_val == INVALID_REGNUM)
+ gcc_unreachable ();
+ return rx_pid_base_regnum_val;
+}
+
+/* Find a SYMBOL_REF in a "standard" MEM address and return its decl. */
+
+static tree
+rx_decl_for_addr (rtx op)
+{
+ if (GET_CODE (op) == MEM)
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == CONST)
+ op = XEXP (op, 0);
+ while (GET_CODE (op) == PLUS)
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == SYMBOL_REF)
+ return SYMBOL_REF_DECL (op);
+ return NULL_TREE;
+}
+
static void rx_print_operand (FILE *, rtx, int);
#define CC_FLAG_S (1 << 0)
@@ -63,6 +99,67 @@ static void rx_print_operand (FILE *, rtx, int);
static unsigned int flags_from_mode (enum machine_mode mode);
static unsigned int flags_from_code (enum rtx_code code);
+/* Return true if OP is a reference to an object in a PID data area. */
+
+enum pid_type
+{
+ PID_NOT_PID = 0, /* The object is not in the PID data area. */
+ PID_ENCODED, /* The object is in the PID data area. */
+ PID_UNENCODED /* The object will be placed in the PID data area, but it has not been placed there yet. */
+};
+
+static enum pid_type
+rx_pid_data_operand (rtx op)
+{
+ tree op_decl;
+
+ if (!TARGET_PID)
+ return PID_NOT_PID;
+
+ if (GET_CODE (op) == PLUS
+ && GET_CODE (XEXP (op, 0)) == REG
+ && GET_CODE (XEXP (op, 1)) == CONST
+ && GET_CODE (XEXP (XEXP (op, 1), 0)) == UNSPEC)
+ return PID_ENCODED;
+
+ op_decl = rx_decl_for_addr (op);
+
+ if (op_decl)
+ {
+ if (TREE_READONLY (op_decl))
+ return PID_UNENCODED;
+ }
+ else
+ {
+ /* Sigh, some special cases. */
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF)
+ return PID_UNENCODED;
+ }
+
+ return PID_NOT_PID;
+}
+
+static rtx
+rx_legitimize_address (rtx x,
+ rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if (rx_pid_data_operand (x) == PID_UNENCODED)
+ {
+ rtx rv = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), x);
+ return rv;
+ }
+
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && REG_P (XEXP (XEXP (x, 0), 0))
+ && REG_P (XEXP (x, 1)))
+ return force_reg (SImode, x);
+
+ return x;
+}
+
/* Return true if OP is a reference to an object in a small data area. */
static bool
@@ -93,6 +190,16 @@ rx_is_legitimate_address (enum machine_mode mode, rtx x,
Post-increment Register Indirect. */
return RTX_OK_FOR_BASE (XEXP (x, 0), strict);
+ switch (rx_pid_data_operand (x))
+ {
+ case PID_UNENCODED:
+ return false;
+ case PID_ENCODED:
+ return true;
+ default:
+ break;
+ }
+
if (GET_CODE (x) == PLUS)
{
rtx arg1 = XEXP (x, 0);
@@ -337,15 +444,17 @@ rx_print_operand_address (FILE * file, rtx addr)
{
addr = XEXP (addr, 0);
gcc_assert (XINT (addr, 1) == UNSPEC_CONST);
-
- addr = XVECEXP (addr, 0, 0);
+
+ /* FIXME: Putting this case label here is an appalling abuse of the C language. */
+ case UNSPEC:
+ addr = XVECEXP (addr, 0, 0);
gcc_assert (CONST_INT_P (addr));
}
/* Fall through. */
case LABEL_REF:
case SYMBOL_REF:
fprintf (file, "#");
-
+ /* Fall through. */
default:
output_addr_const (file, addr);
break;
@@ -389,9 +498,11 @@ rx_assemble_integer (rtx x, unsigned int size, int is_aligned)
%B Print an integer comparison name.
%C Print a control register name.
%F Print a condition code flag name.
+ %G Register used for small-data-area addressing
%H Print high part of a DImode register, integer or address.
%L Print low part of a DImode register, integer or address.
%N Print the negation of the immediate value.
+ %P Register used for PID addressing
%Q If the operand is a MEM, then correctly generate
register indirect or register relative addressing.
%R Like %Q but for zero-extending loads. */
@@ -400,6 +511,16 @@ static void
rx_print_operand (FILE * file, rtx op, int letter)
{
bool unsigned_load = false;
+ bool print_hash = true;
+
+ if (letter == 'A'
+ && ((GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == UNSPEC)
+ || GET_CODE (op) == UNSPEC))
+ {
+ print_hash = false;
+ letter = 0;
+ }
switch (letter)
{
@@ -516,7 +637,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
case 0xb: fprintf (file, "fintv"); break;
case 0xc: fprintf (file, "intb"); break;
default:
- warning (0, "unreocgnized control register number: %d - using 'psw'",
+ warning (0, "unrecognized control register number: %d - using 'psw'",
(int) INTVAL (op));
fprintf (file, "psw");
break;
@@ -538,6 +659,10 @@ rx_print_operand (FILE * file, rtx op, int letter)
}
break;
+ case 'G':
+ fprintf (file, "%s", reg_names [rx_gp_base_regnum ()]);
+ break;
+
case 'H':
switch (GET_CODE (op))
{
@@ -599,6 +724,10 @@ rx_print_operand (FILE * file, rtx op, int letter)
rx_print_integer (file, - INTVAL (op));
break;
+ case 'P':
+ fprintf (file, "%s", reg_names [rx_pid_base_regnum ()]);
+ break;
+
case 'R':
gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4);
unsigned_load = true;
@@ -667,6 +796,24 @@ rx_print_operand (FILE * file, rtx op, int letter)
/* Fall through. */
default:
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == UNSPEC)
+ op = XEXP (op, 0);
+ else if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+ {
+ if (print_hash)
+ fprintf (file, "#");
+ fprintf (file, "(");
+ rx_print_operand (file, XEXP (XEXP (op, 0), 0), 'A');
+ fprintf (file, " + ");
+ output_addr_const (file, XEXP (XEXP (op, 0), 1));
+ fprintf (file, ")");
+ return;
+ }
+
switch (GET_CODE (op))
{
case MULT:
@@ -721,20 +868,52 @@ rx_print_operand (FILE * file, rtx op, int letter)
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_SINGLE (rv, val);
- fprintf (file, TARGET_AS100_SYNTAX ? "#0%lxH" : "#0x%lx", val);
+ if (print_hash)
+ fprintf (file, "#");
+ fprintf (file, TARGET_AS100_SYNTAX ? "0%lxH" : "0x%lx", val);
break;
}
case CONST_INT:
- fprintf (file, "#");
+ if (print_hash)
+ fprintf (file, "#");
rx_print_integer (file, INTVAL (op));
break;
- case SYMBOL_REF:
+ case UNSPEC:
+ switch (XINT (op, 1))
+ {
+ case UNSPEC_PID_ADDR:
+ {
+ rtx sym, add;
+
+ if (print_hash)
+ fprintf (file, "#");
+ sym = XVECEXP (op, 0, 0);
+ add = NULL_RTX;
+ fprintf (file, "(");
+ if (GET_CODE (sym) == PLUS)
+ {
+ add = XEXP (sym, 1);
+ sym = XEXP (sym, 0);
+ }
+ output_addr_const (file, sym);
+ if (add != NULL_RTX)
+ {
+ fprintf (file, "+");
+ output_addr_const (file, add);
+ }
+ fprintf (file, "-__pid_base");
+ fprintf (file, ")");
+ return;
+ }
+ }
+ /* Fall through */
+
case CONST:
+ case SYMBOL_REF:
case LABEL_REF:
case CODE_LABEL:
- case UNSPEC:
rx_print_operand_address (file, op);
break;
@@ -745,6 +924,29 @@ rx_print_operand (FILE * file, rtx op, int letter)
}
}
+/* Maybe convert an operand into its PID format. */
+
+rtx
+rx_maybe_pidify_operand (rtx op, int copy_to_reg)
+{
+ if (rx_pid_data_operand (op) == PID_UNENCODED)
+ {
+ if (GET_CODE (op) == MEM)
+ {
+ rtx a = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), XEXP (op, 0));
+ op = replace_equiv_address (op, a);
+ }
+ else
+ {
+ op = gen_pid_addr (gen_rtx_REG (SImode, rx_pid_base_regnum ()), op);
+ }
+
+ if (copy_to_reg)
+ op = copy_to_mode_reg (GET_MODE (op), op);
+ }
+ return op;
+}
+
/* Returns an assembler template for a move instruction. */
char *
@@ -784,13 +986,15 @@ rx_gen_move_template (rtx * operands, bool is_movu)
gcc_unreachable ();
}
- if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
- src_template = "%%gp(%A1)[r13]";
+ if (MEM_P (src) && rx_pid_data_operand (XEXP (src, 0)) == PID_UNENCODED)
+ src_template = "(%A1-__pid_base)[%P1]";
+ else if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0)))
+ src_template = "%%gp(%A1)[%G1]";
else
src_template = "%1";
if (MEM_P (dest) && rx_small_data_operand (XEXP (dest, 0)))
- dst_template = "%%gp(%A0)[r13]";
+ dst_template = "%%gp(%A0)[%G0]";
else
dst_template = "%0";
@@ -996,8 +1200,21 @@ rx_conditional_register_usage (void)
{
static bool using_fixed_regs = false;
+ if (TARGET_PID)
+ {
+ rx_pid_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
+ fixed_regs[rx_pid_base_regnum_val] = call_used_regs [rx_pid_base_regnum_val] = 1;
+ }
+
if (rx_small_data_limit > 0)
- fixed_regs[GP_BASE_REGNUM] = call_used_regs [GP_BASE_REGNUM] = 1;
+ {
+ if (TARGET_PID)
+ rx_gp_base_regnum_val = rx_pid_base_regnum_val - 1;
+ else
+ rx_gp_base_regnum_val = GP_BASE_REGNUM - rx_num_interrupt_regs;
+
+ fixed_regs[rx_gp_base_regnum_val] = call_used_regs [rx_gp_base_regnum_val] = 1;
+ }
if (use_fixed_regs != using_fixed_regs)
{
@@ -2338,8 +2555,10 @@ rx_option_override (void)
fixed_regs[13] = call_used_regs [13] = 1;
/* Fall through. */
case 0:
+ rx_num_interrupt_regs = opt->value;
break;
default:
+ rx_num_interrupt_regs = 0;
/* Error message already given because rx_handle_option
returned false. */
break;
@@ -2444,7 +2663,7 @@ rx_is_legitimate_constant (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
return true;
case UNSPEC:
- return XINT (x, 1) == UNSPEC_CONST;
+ return XINT (x, 1) == UNSPEC_CONST || XINT (x, 1) == UNSPEC_PID_ADDR;
default:
/* FIXME: Can this ever happen ? */
@@ -3031,6 +3250,9 @@ rx_adjust_insn_length (rtx insn, int current_length)
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P rx_is_legitimate_constant
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS rx_legitimize_address
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rx.h"
diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
index 67e8ce1c577..10b16bda261 100644
--- a/gcc/config/rx/rx.h
+++ b/gcc/config/rx/rx.h
@@ -63,6 +63,13 @@
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+#undef CPP_SPEC
+#define CPP_SPEC "\
+%{mpid:-D_RX_PID=1} \
+%{mint-register=*:-D_RX_INT_REGISTERS=%*} \
+%{msmall-data-limit*:-D_RX_SMALL_DATA} \
+"
+
#undef ASM_SPEC
#define ASM_SPEC "\
%{mbig-endian-data:-mbig-endian-data} \
@@ -70,6 +77,8 @@
%{!m64bit-doubles:-m32bit-doubles} \
%{msmall-data-limit*:-msmall-data-limit} \
%{mrelax:-relax} \
+%{mpid} \
+%{mint-register=*} \
"
#undef LIB_SPEC
@@ -200,14 +209,17 @@ enum reg_class
#define STRUCT_VAL_REGNUM 15
#define CC_REGNUM 16
-/* This is the register which is used to hold the address of the start
- of the small data area, if that feature is being used. Note - this
- register must not be call_used because otherwise library functions
- that are compiled without small data support might clobber it.
+/* This is the register which will probably be used to hold the address of
+ the start of the small data area, if -msmall-data-limit is being used,
+ or the address of the constant data area if -mpid is being used. If both
+ features are in use then two consecutive registers will be used.
- FIXME: The function gcc/config/rx/rx.c:rx_gen_move_template() has a
- built in copy of this register's name, rather than constructing the
- name from this #define. */
+ Note - these registers must not be call_used because otherwise library
+ functions that are compiled without -msmall-data-limit/-mpid support
+ might clobber them.
+
+ Note that the actual values used depends on other options; use
+ rx_gp_base_regnum() and rx_pid_base_regnum() instead. */
#define GP_BASE_REGNUM 13
#define ELIMINABLE_REGS \
@@ -444,13 +456,15 @@ typedef unsigned int CUMULATIVE_ARGS;
VALUE)
/* This is how to output an element of a case-vector that is relative.
- Note: The local label referenced by the "3b" below is emitted by
+ Note: The local label referenced by the "1b" below is emitted by
the tablejump insn. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
fprintf (FILE, TARGET_AS100_SYNTAX \
? "\t.LWORD L%d - ?-\n" : "\t.long .L%d - 1b\n", VALUE)
+#define CASE_VECTOR_PC_RELATIVE (TARGET_PID)
+
#define ASM_OUTPUT_SIZE_DIRECTIVE(STREAM, NAME, SIZE) \
do \
{ \
@@ -595,7 +609,7 @@ typedef unsigned int CUMULATIVE_ARGS;
/* For PIC put jump tables into the text section so that the offsets that
they contain are always computed between two same-section symbols. */
-#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
+#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_PID || flag_pic)
/* This is a version of REG_P that also returns TRUE for SUBREGs. */
#define RX_REG_P(rtl) (REG_P (rtl) || GET_CODE (rtl) == SUBREG)
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index f082ed2763c..a55b62f8f57 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -73,6 +73,8 @@
(UNSPEC_BUILTIN_SAT 49)
(UNSPEC_BUILTIN_SETPSW 50)
(UNSPEC_BUILTIN_WAIT 51)
+
+ (UNSPEC_PID_ADDR 52)
]
)
@@ -330,9 +332,9 @@
(match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
- { return flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
- : "\n1:\tbra\t%0")
- : "jmp\t%0";
+ { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
+ : "\n1:\tbra\t%0")
+ : "\n1:jmp\t%0";
}
[(set_attr "timings" "33")
(set_attr "length" "2")]
@@ -556,8 +558,18 @@
(match_operand:register_modes 1 "general_operand"))]
""
{
- if (MEM_P (operand0) && MEM_P (operand1))
- operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1);
+ if (MEM_P (operands[0]) && MEM_P (operands[1]))
+ operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
+ operands[0] = rx_maybe_pidify_operand (operands[0], 0);
+ operands[1] = rx_maybe_pidify_operand (operands[1], 0);
+ if (GET_CODE (operands[0]) != REG
+ && GET_CODE (operands[1]) == PLUS)
+ operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
+ if (GET_CODE (operands[1]) == PLUS && GET_MODE (operands[1]) == SImode)
+ {
+ emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));
+ DONE;
+ }
if (CONST_INT_P (operand1)
&& ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
FAIL;
@@ -566,13 +578,13 @@
(define_insn "*mov<register_modes:mode>_internal"
[(set (match_operand:register_modes
- 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q")
+ 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q,r")
(match_operand:register_modes
- 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i"))]
+ 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))]
""
{ return rx_gen_move_template (operands, false); }
- [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8")
- (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11")]
+ [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8")
+ (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")]
)
(define_insn "extend<small_int_modes:mode>si2"
@@ -830,7 +842,20 @@
[(set_attr "length" "2,3")]
)
-(define_insn "addsi3"
+(define_expand "addsi3"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "rx_source_operand" "")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+ "
+ operands[0] = rx_maybe_pidify_operand (operands[0], 1);
+ operands[1] = rx_maybe_pidify_operand (operands[1], 1);
+ operands[2] = rx_maybe_pidify_operand (operands[2], 1);
+ "
+)
+
+(define_insn "addsi3_internal"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
(match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
@@ -901,7 +926,7 @@
(match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
(clobber (reg:CC CC_REG))]
"reload_completed"
- "adc %2,%0"
+ "adc\t%2, %0"
[(set_attr "timings" "11,11,11,11,11,33")
(set_attr "length" "3,4,5,6,7,6")]
)
@@ -922,7 +947,7 @@
(match_dup 2))
(const_int 0)))]
"reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
- "adc %2,%0"
+ "adc\t%2, %0"
[(set_attr "timings" "11,11,11,11,11,33")
(set_attr "length" "3,4,5,6,7,6")]
)
@@ -980,7 +1005,7 @@
})
(define_insn_and_split "adddi3_internal"
- [(set (match_operand:SI 0 "register_operand" "=r")
+ [(set (match_operand:SI 0 "register_operand" "=&r")
(plus:SI (match_operand:SI 2 "register_operand" "r")
(match_operand:SI 3 "rx_source_operand" "riQ")))
(set (match_operand:SI 1 "register_operand" "=r")
@@ -1163,22 +1188,22 @@
(set_attr "timings" "22,44")]
)
-(define_insn "smax<int_modes:mode>3"
- [(set (match_operand:int_modes 0 "register_operand" "=r,r,r,r,r,r")
- (smax:int_modes (match_operand:int_modes 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:int_modes 2 "rx_source_operand"
- "r,Sint08,Sint16,Sint24,i,Q")))]
+(define_insn "smaxsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
+ (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
+ (match_operand:SI 2 "rx_source_operand"
+ "r,Sint08,Sint16,Sint24,i,Q")))]
""
"max\t%Q2, %0"
[(set_attr "length" "3,4,5,6,7,6")
(set_attr "timings" "11,11,11,11,11,33")]
)
-(define_insn "smin<int_modes:mode>3"
- [(set (match_operand:int_modes 0 "register_operand" "=r,r,r,r,r,r")
- (smin:int_modes (match_operand:int_modes 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:int_modes 2 "rx_source_operand"
- "r,Sint08,Sint16,Sint24,i,Q")))]
+(define_insn "sminsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
+ (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
+ (match_operand:SI 2 "rx_source_operand"
+ "r,Sint08,Sint16,Sint24,i,Q")))]
""
"min\t%Q2, %0"
[(set_attr "length" "3,4,5,6,7,6")
@@ -2583,3 +2608,10 @@
"nop"
[(set_attr "length" "1")]
)
+
+(define_expand "pid_addr"
+ [(plus:SI (match_operand:SI 0)
+ (const:SI (unspec:SI [(match_operand:SI 1)] UNSPEC_PID_ADDR)))]
+ ""
+ ""
+)
diff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt
index 4a84effdcdb..308bf0c8ada 100644
--- a/gcc/config/rx/rx.opt
+++ b/gcc/config/rx/rx.opt
@@ -112,3 +112,9 @@ Specifies the number of registers to reserve for interrupt handlers.
msave-acc-in-interrupts
Target Mask(SAVE_ACC_REGISTER)
Specifies whether interrupt functions should save and restore the accumulator register.
+
+;---------------------------------------------------
+
+mpid
+Target Mask(PID)
+Enables Position-Independent-Data (PID) mode.
diff --git a/gcc/config/rx/t-rx b/gcc/config/rx/t-rx
index 38893143981..ad667bcc5c9 100644
--- a/gcc/config/rx/t-rx
+++ b/gcc/config/rx/t-rx
@@ -20,8 +20,8 @@
# Enable multilibs:
-MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data
-MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data
+MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data mpid
+MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data pid
MULTILIB_MATCHES = nofpu=mnofpu nofpu=mcpu?rx200
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 22f05f9fd21..ffca91a107a 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -3604,7 +3604,8 @@ s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
{
rtx insn;
- gcc_assert (flag_pic);
+ if (!flag_pic)
+ emit_insn (s390_load_got ());
if (!s390_tls_symbol)
s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset");
@@ -7859,6 +7860,12 @@ s390_load_got (void)
{
rtx insns;
+ /* We cannot use pic_offset_table_rtx here since we use this
+ function also for non-pic if __tls_get_offset is called and in
+ that case PIC_OFFSET_TABLE_REGNUM as well as pic_offset_table_rtx
+ aren't usable. */
+ rtx got_rtx = gen_rtx_REG (Pmode, 12);
+
if (!got_symbol)
{
got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
@@ -7869,7 +7876,7 @@ s390_load_got (void)
if (TARGET_CPU_ZARCH)
{
- emit_move_insn (pic_offset_table_rtx, got_symbol);
+ emit_move_insn (got_rtx, got_symbol);
}
else
{
@@ -7880,13 +7887,13 @@ s390_load_got (void)
offset = gen_rtx_CONST (Pmode, offset);
offset = force_const_mem (Pmode, offset);
- emit_move_insn (pic_offset_table_rtx, offset);
+ emit_move_insn (got_rtx, offset);
offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)),
UNSPEC_LTREL_BASE);
- offset = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
+ offset = gen_rtx_PLUS (Pmode, got_rtx, offset);
- emit_move_insn (pic_offset_table_rtx, offset);
+ emit_move_insn (got_rtx, offset);
}
insns = get_insns ();
@@ -9827,8 +9834,7 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
/* s390_function_ok_for_sibcall should
have denied sibcalls in this case. */
gcc_assert (retaddr_reg != NULL_RTX);
-
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, 12));
}
return insn;
}
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 018f6b49214..4c9a40f6e8e 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -367,6 +367,10 @@
(define_mode_iterator DW [(TI "TARGET_ZARCH") (DI "!TARGET_ZARCH")])
(define_mode_iterator W [(DI "TARGET_ZARCH") (SI "!TARGET_ZARCH")])
+;; Used by the umul pattern to express modes having half the size.
+(define_mode_attr DWH [(TI "DI") (DI "SI")])
+(define_mode_attr dwh [(TI "di") (DI "si")])
+
;; This mode iterator allows the QI and HI patterns to be defined from
;; the same template.
(define_mode_iterator HQI [HI QI])
@@ -5456,21 +5460,22 @@
(set_attr "cpu_facility" "*,*,z10")])
;
-; umulsidi3 instruction pattern(s).
+; umul instruction pattern(s).
;
-(define_insn "umulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (mult:DI (zero_extend:DI
- (match_operand:SI 1 "register_operand" "%0,0"))
- (zero_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,RT"))))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
+; mlr, ml, mlgr, mlg
+(define_insn "umul<dwh><mode>3"
+ [(set (match_operand:DW 0 "register_operand" "=d, d")
+ (mult:DW (zero_extend:DW
+ (match_operand:<DWH> 1 "register_operand" "%0, 0"))
+ (zero_extend:DW
+ (match_operand:<DWH> 2 "nonimmediate_operand" " d,RT"))))]
+ "TARGET_CPU_ZARCH"
"@
- mlr\t%0,%2
- ml\t%0,%2"
+ ml<tg>r\t%0,%2
+ ml<tg>\t%0,%2"
[(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "imulsi")])
+ (set_attr "type" "imul<dwh>")])
;
; mul(tf|df|sf|td|dd)3 instruction pattern(s).
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index c0bfdd3af49..03c3c48c0e4 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -242,7 +242,7 @@ static void sh_file_start (void);
static int flow_dependent_p (rtx, rtx);
static void flow_dependent_p_1 (rtx, const_rtx, void *);
static int shiftcosts (rtx);
-static int and_xor_ior_costs (rtx, int code);
+static int and_xor_ior_costs (rtx, int);
static int addsubcosts (rtx);
static int multcosts (rtx);
static bool unspec_caller_rtx_p (rtx);
@@ -2995,6 +2995,20 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
*total = 8;
return true;
+ case EQ:
+ /* An and with a constant compared against zero is
+ most likely going to be a TST #imm, R0 instruction.
+ Notice that this does not catch the zero_extract variants from
+ the md file. */
+ if (GET_CODE (XEXP (x, 0)) == AND
+ && CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 0)
+ {
+ *total = 1;
+ return true;
+ }
+ else
+ return false;
+
case CONST:
case LABEL_REF:
case SYMBOL_REF:
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index ef42a1bfc9d..1e654801334 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -1195,6 +1195,9 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
#define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
&& ((HOST_WIDE_INT)(VALUE)) <= 255)
+#define ZERO_EXTRACT_ANDMASK(EXTRACT_SZ_RTX, EXTRACT_POS_RTX)\
+ (((1 << INTVAL (EXTRACT_SZ_RTX)) - 1) << INTVAL (EXTRACT_POS_RTX))
+
#if 0
#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
((((REGCLASS_HAS_FP_REG (CLASS) \
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 63cb9393653..ce660185dd3 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -585,15 +585,164 @@
;; SImode signed integer comparisons
;; -------------------------------------------------------------------------
-(define_insn ""
+;; Various patterns to generate the TST #imm, R0 instruction.
+;; Although this adds some pressure on the R0 register, it can potentially
+;; result in faster code, even if the operand has to be moved to R0 first.
+;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
+;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
+;; is an EX group instruction but still can be executed in parallel with the
+;; MT group MOV Rm, Rn instruction.
+
+;; Usual TST #imm, R0 patterns for SI, HI and QI
+;; This is usually used for bit patterns other than contiguous bits
+;; and single bits.
+
+(define_insn "tstsi_t"
[(set (reg:SI T_REG)
- (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
+ (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
(match_operand:SI 1 "logical_operand" "K08,r"))
(const_int 0)))]
"TARGET_SH1"
"tst %1,%0"
[(set_attr "type" "mt_group")])
+(define_insn "tsthi_t"
+ [(set (reg:SI T_REG)
+ (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
+ (match_operand 1 "const_int_operand")) 0)
+ (const_int 0)))]
+ "TARGET_SH1
+ && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
+ "tst %1,%0"
+ [(set_attr "type" "mt_group")])
+
+(define_insn "tstqi_t"
+ [(set (reg:SI T_REG)
+ (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
+ (match_operand 1 "const_int_operand")) 0)
+ (const_int 0)))]
+ "TARGET_SH1
+ && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
+ || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
+{
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
+ return "tst %1,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; Test low QI subreg against zero.
+;; This avoids unecessary zero extension before the test.
+
+(define_insn "tstqi_t_zero"
+ [(set (reg:SI T_REG)
+ (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
+ "TARGET_SH1"
+ "tst #255,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract LSB, negate and store in T bit.
+
+(define_insn "tstsi_t_and_not"
+ [(set (reg:SI T_REG)
+ (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
+ (const_int 1)))]
+ "TARGET_SH1"
+ "tst #1,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract contiguous bits and compare them against zero.
+
+(define_insn "tstsi_t_zero_extract_eq"
+ [(set (reg:SI T_REG)
+ (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand"))
+ (const_int 0)))]
+ "TARGET_SH1
+ && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
+{
+ operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
+ return "tst %1,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; This split is required when testing bits in a QI subreg.
+
+(define_split
+ [(set (reg:SI T_REG)
+ (eq:SI (if_then_else:SI (zero_extract:SI
+ (match_operand 0 "logical_operand" "")
+ (match_operand 1 "const_int_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand 3 "const_int_operand")
+ (const_int 0))
+ (const_int 0)))]
+ "TARGET_SH1
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+ [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
+ (const_int 0)))]
+ "
+{
+ if (GET_MODE (operands[0]) == QImode)
+ operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
+}")
+
+;; Extract single bit, negate and store it in the T bit.
+;; Not used for SH4A.
+
+(define_insn "tstsi_t_zero_extract_xor"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand"))
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+ "tst %3,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A little endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_little"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI
+ (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand")) 0)
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1 && TARGET_LITTLE_ENDIAN
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+ == (INTVAL (operands[3]) & 255)
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+ return "tst %3,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A big endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_big"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI
+ (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand")) 3)
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+ == (INTVAL (operands[3]) & 255)
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+ return "tst %3,%0";
+}
+ [(set_attr "type" "mt_group")])
+
;; ??? Perhaps should only accept reg/constant if the register is reg 0.
;; That would still allow reload to create cmpi instructions, but would
;; perhaps allow forcing the constant into a register when that is better.
@@ -1157,7 +1306,7 @@
&& (arith_reg_operand (operands[1], SImode)
|| (immediate_operand (operands[1], SImode)
&& satisfies_constraint_I08 (operands[1])))"
- "bt 0f\;mov %1,%0\\n0:"
+ "bt 0f\;mov %1,%0\\n0:"
[(set_attr "type" "mt_group,arith") ;; poor approximation
(set_attr "length" "4")])
@@ -1170,7 +1319,7 @@
&& (arith_reg_operand (operands[1], SImode)
|| (immediate_operand (operands[1], SImode)
&& satisfies_constraint_I08 (operands[1])))"
- "bf 0f\;mov %1,%0\\n0:"
+ "bf 0f\;mov %1,%0\\n0:"
[(set_attr "type" "mt_group,arith") ;; poor approximation
(set_attr "length" "4")])
@@ -3015,9 +3164,9 @@ label:
;; -------------------------------------------------------------------------
(define_insn "*andsi3_compact"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
+ [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
(and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
- (match_operand:SI 2 "logical_operand" "r,K08")))]
+ (match_operand:SI 2 "logical_operand" "K08,r")))]
"TARGET_SH1"
"and %2,%0"
[(set_attr "type" "arith")])
diff --git a/gcc/config/sparc/driver-sparc.c b/gcc/config/sparc/driver-sparc.c
index 96227289db5..3973fbceece 100644
--- a/gcc/config/sparc/driver-sparc.c
+++ b/gcc/config/sparc/driver-sparc.c
@@ -58,7 +58,7 @@ static const struct cpu_names {
{ "SPARC-T3", "niagara3" },
{ "SPARC-T4", "niagara4" },
#else
- { "SuperSPARC", "supersparc" },
+ { "SuperSparc", "supersparc" },
{ "HyperSparc", "hypersparc" },
{ "SpitFire", "ultrasparc" },
{ "BlackBird", "ultrasparc" },
diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h
index 0ad4b3482f1..443c7966405 100644
--- a/gcc/config/sparc/linux.h
+++ b/gcc/config/sparc/linux.h
@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see
/* -mcpu=native handling only makes sense with compiler running on
a SPARC chip. */
-#if defined(__sparc__)
+#if defined(__sparc__) && defined(__linux__)
extern const char *host_detect_local_cpu (int argc, const char **argv);
# define EXTRA_SPEC_FUNCTIONS \
{ "local_cpu_detect", host_detect_local_cpu },
diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h
index 3c83d2d0a6e..a51a2f0e1c7 100644
--- a/gcc/config/sparc/linux64.h
+++ b/gcc/config/sparc/linux64.h
@@ -31,7 +31,9 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
-#ifdef TARGET_64BIT_DEFAULT
+/* On Linux, the combination sparc64-* --with-cpu=v8 is supported and
+ selects a 32-bit compiler. */
+#if defined(TARGET_64BIT_DEFAULT) && TARGET_CPU_DEFAULT >= TARGET_CPU_v9
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_STACK_BIAS + \
@@ -137,7 +139,7 @@ along with GCC; see the file COPYING3. If not see
/* -mcpu=native handling only makes sense with compiler running on
a SPARC chip. */
-#if defined(__sparc__)
+#if defined(__sparc__) && defined(__linux__)
extern const char *host_detect_local_cpu (int argc, const char **argv);
# define EXTRA_SPEC_FUNCTIONS \
{ "local_cpu_detect", host_detect_local_cpu },
diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md
index 21399b5902a..f0be14997af 100644
--- a/gcc/config/sparc/predicates.md
+++ b/gcc/config/sparc/predicates.md
@@ -24,11 +24,6 @@
(and (match_code "const_int,const_double,const_vector")
(match_test "op == CONST0_RTX (mode)")))
-;; Return true if OP is the one constant for MODE.
-(define_predicate "const_one_operand"
- (and (match_code "const_int,const_double,const_vector")
- (match_test "op == CONST1_RTX (mode)")))
-
;; Return true if the integer representation of OP is
;; all-ones.
(define_predicate "const_all_ones_operand"
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index fea60d0543b..ba2ec35e20a 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -181,7 +181,7 @@ along with GCC; see the file COPYING3. If not see
/* -mcpu=native handling only makes sense with compiler running on
a SPARC chip. */
-#if defined(__sparc__)
+#if defined(__sparc__) && defined(__SVR4)
extern const char *host_detect_local_cpu (int argc, const char **argv);
# define EXTRA_SPEC_FUNCTIONS \
{ "local_cpu_detect", host_detect_local_cpu },
diff --git a/gcc/config/sparc/sparc-modes.def b/gcc/config/sparc/sparc-modes.def
index ed135ccc1b7..a5849c984b1 100644
--- a/gcc/config/sparc/sparc-modes.def
+++ b/gcc/config/sparc/sparc-modes.def
@@ -45,4 +45,6 @@ CC_MODE (CCFPE);
/* Vector modes. */
VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
-VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODE (INT, DI, 1); /* V1DI */
+VECTOR_MODE (INT, SI, 1); /* V1SI */
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index dfa461a5f58..4b15b82c07a 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -105,6 +105,9 @@ extern int v9_regcmp_p (enum rtx_code);
extern int sparc_check_64 (rtx, rtx);
extern rtx gen_df_reg (rtx, int);
extern void sparc_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
+extern const char *output_v8plus_mult (rtx, rtx *, const char *);
+extern void sparc_expand_vector_init (rtx, rtx);
+extern void sparc_expand_vec_perm_bmask(enum machine_mode, rtx);
#endif /* RTX_CODE */
#endif /* __SPARC_PROTOS_H__ */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 4df9f6a8088..a6601def3be 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -444,6 +444,7 @@ static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
HOST_WIDE_INT, const_tree);
+static void sparc_reorg (void);
static struct machine_function * sparc_init_machine_status (void);
static bool sparc_cannot_force_const_mem (enum machine_mode, rtx);
static rtx sparc_tls_get_addr (void);
@@ -582,6 +583,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG sparc_reorg
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
#undef TARGET_ADDRESS_COST
@@ -696,6 +700,61 @@ char sparc_hard_reg_printed[8];
struct gcc_target targetm = TARGET_INITIALIZER;
+static void
+dump_target_flag_bits (const int flags)
+{
+ if (flags & MASK_64BIT)
+ fprintf (stderr, "64BIT ");
+ if (flags & MASK_APP_REGS)
+ fprintf (stderr, "APP_REGS ");
+ if (flags & MASK_FASTER_STRUCTS)
+ fprintf (stderr, "FASTER_STRUCTS ");
+ if (flags & MASK_FLAT)
+ fprintf (stderr, "FLAT ");
+ if (flags & MASK_FMAF)
+ fprintf (stderr, "FMAF ");
+ if (flags & MASK_FPU)
+ fprintf (stderr, "FPU ");
+ if (flags & MASK_HARD_QUAD)
+ fprintf (stderr, "HARD_QUAD ");
+ if (flags & MASK_POPC)
+ fprintf (stderr, "POPC ");
+ if (flags & MASK_PTR64)
+ fprintf (stderr, "PTR64 ");
+ if (flags & MASK_STACK_BIAS)
+ fprintf (stderr, "STACK_BIAS ");
+ if (flags & MASK_UNALIGNED_DOUBLES)
+ fprintf (stderr, "UNALIGNED_DOUBLES ");
+ if (flags & MASK_V8PLUS)
+ fprintf (stderr, "V8PLUS ");
+ if (flags & MASK_VIS)
+ fprintf (stderr, "VIS ");
+ if (flags & MASK_VIS2)
+ fprintf (stderr, "VIS2 ");
+ if (flags & MASK_VIS3)
+ fprintf (stderr, "VIS3 ");
+ if (flags & MASK_DEPRECATED_V8_INSNS)
+ fprintf (stderr, "DEPRECATED_V8_INSNS ");
+ if (flags & MASK_LITTLE_ENDIAN)
+ fprintf (stderr, "LITTLE_ENDIAN ");
+ if (flags & MASK_SPARCLET)
+ fprintf (stderr, "SPARCLET ");
+ if (flags & MASK_SPARCLITE)
+ fprintf (stderr, "SPARCLITE ");
+ if (flags & MASK_V8)
+ fprintf (stderr, "V8 ");
+ if (flags & MASK_V9)
+ fprintf (stderr, "V9 ");
+}
+
+static void
+dump_target_flags (const char *prefix, const int flags)
+{
+ fprintf (stderr, "%s: (%08x) [ ", prefix, flags);
+ dump_target_flag_bits (flags);
+ fprintf(stderr, "]\n");
+}
+
/* Validate and override various options, and do some machine dependent
initialization. */
@@ -741,49 +800,93 @@ sparc_option_override (void)
/* Table of values for -m{cpu,tune}=. This must match the order of
the PROCESSOR_* enumeration. */
static struct cpu_table {
+ const char *const name;
const int disable;
const int enable;
} const cpu_table[] = {
- { MASK_ISA, 0 },
- { MASK_ISA, 0 },
- { MASK_ISA, MASK_V8 },
+ { "v7", MASK_ISA, 0 },
+ { "cypress", MASK_ISA, 0 },
+ { "v8", MASK_ISA, MASK_V8 },
/* TI TMS390Z55 supersparc */
- { MASK_ISA, MASK_V8 },
- { MASK_ISA, MASK_V8|MASK_FPU },
+ { "supersparc", MASK_ISA, MASK_V8 },
+ { "hypersparc", MASK_ISA, MASK_V8|MASK_FPU },
/* LEON */
- { MASK_ISA, MASK_V8|MASK_FPU },
- { MASK_ISA, MASK_SPARCLITE },
+ { "leon", MASK_ISA, MASK_V8|MASK_FPU },
+ { "sparclite", MASK_ISA, MASK_SPARCLITE },
/* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
- { MASK_ISA|MASK_FPU, MASK_SPARCLITE },
+ { "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
/* The Fujitsu MB86934 is the recent sparclite chip, with an FPU. */
- { MASK_ISA, MASK_SPARCLITE|MASK_FPU },
- { MASK_ISA|MASK_FPU, MASK_SPARCLITE },
- { MASK_ISA, MASK_SPARCLET },
+ { "f934", MASK_ISA, MASK_SPARCLITE|MASK_FPU },
+ { "sparclite86x", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
+ { "sparclet", MASK_ISA, MASK_SPARCLET },
/* TEMIC sparclet */
- { MASK_ISA, MASK_SPARCLET },
- { MASK_ISA, MASK_V9 },
+ { "tsc701", MASK_ISA, MASK_SPARCLET },
+ { "v9", MASK_ISA, MASK_V9 },
/* UltraSPARC I, II, IIi */
- { MASK_ISA,
+ { "ultrasparc", MASK_ISA,
/* Although insns using %y are deprecated, it is a clear win. */
- MASK_V9|MASK_DEPRECATED_V8_INSNS},
+ MASK_V9|MASK_DEPRECATED_V8_INSNS },
/* UltraSPARC III */
/* ??? Check if %y issue still holds true. */
- { MASK_ISA,
- MASK_V9|MASK_DEPRECATED_V8_INSNS|MASK_VIS2},
+ { "ultrasparc3", MASK_ISA,
+ MASK_V9|MASK_DEPRECATED_V8_INSNS|MASK_VIS2 },
/* UltraSPARC T1 */
- { MASK_ISA,
- MASK_V9|MASK_DEPRECATED_V8_INSNS},
+ { "niagara", MASK_ISA,
+ MASK_V9|MASK_DEPRECATED_V8_INSNS },
/* UltraSPARC T2 */
- { MASK_ISA, MASK_V9|MASK_VIS2},
+ { "niagara2", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS2 },
/* UltraSPARC T3 */
- { MASK_ISA, MASK_V9|MASK_VIS2|MASK_VIS3|MASK_FMAF},
+ { "niagara3", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF },
/* UltraSPARC T4 */
- { MASK_ISA, MASK_V9|MASK_VIS2|MASK_VIS3|MASK_FMAF},
+ { "niagara4", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF },
};
const struct cpu_table *cpu;
unsigned int i;
int fpu;
+ if (sparc_debug_string != NULL)
+ {
+ const char *q;
+ char *p;
+
+ p = ASTRDUP (sparc_debug_string);
+ while ((q = strtok (p, ",")) != NULL)
+ {
+ bool invert;
+ int mask;
+
+ p = NULL;
+ if (*q == '!')
+ {
+ invert = true;
+ q++;
+ }
+ else
+ invert = false;
+
+ if (! strcmp (q, "all"))
+ mask = MASK_DEBUG_ALL;
+ else if (! strcmp (q, "options"))
+ mask = MASK_DEBUG_OPTIONS;
+ else
+ error ("unknown -mdebug-%s switch", q);
+
+ if (invert)
+ sparc_debug &= ~mask;
+ else
+ sparc_debug |= mask;
+ }
+ }
+
+ if (TARGET_DEBUG_OPTIONS)
+ {
+ dump_target_flags("Initial target_flags", target_flags);
+ dump_target_flags("target_flags_explicit", target_flags_explicit);
+ }
+
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
@@ -845,12 +948,31 @@ sparc_option_override (void)
gcc_assert (def->cpu != -1);
sparc_cpu_and_features = def->processor;
}
+
+ if ((target_flags & MASK_V8PLUS)
+ && sparc_cpu_and_features < PROCESSOR_V9)
+ sparc_cpu_and_features = PROCESSOR_V9;
+
if (!global_options_set.x_sparc_cpu)
sparc_cpu = sparc_cpu_and_features;
cpu = &cpu_table[(int) sparc_cpu_and_features];
+
+ if (TARGET_DEBUG_OPTIONS)
+ {
+ fprintf (stderr, "sparc_cpu_and_features: %s\n", cpu->name);
+ fprintf (stderr, "sparc_cpu: %s\n",
+ cpu_table[(int) sparc_cpu].name);
+ dump_target_flags ("cpu->disable", cpu->disable);
+ dump_target_flags ("cpu->enable", cpu->enable);
+ }
+
target_flags &= ~cpu->disable;
- target_flags |= cpu->enable;
+ target_flags |= (cpu->enable
+#ifndef HAVE_AS_FMAF_HPC_VIS3
+ & ~(MASK_FMAF | MASK_VIS3)
+#endif
+ );
/* If -mfpu or -mno-fpu was explicitly used, don't override with
the processor default. */
@@ -968,6 +1090,9 @@ sparc_option_override (void)
target_flags |= MASK_LONG_DOUBLE_128;
#endif
+ if (TARGET_DEBUG_OPTIONS)
+ dump_target_flags ("Final target_flags", target_flags);
+
maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES,
((sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_NIAGARA
@@ -6789,7 +6914,7 @@ sparc_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
{
tree tmp = create_tmp_var (type, "va_arg_tmp");
tree dest_addr = build_fold_addr_expr (tmp);
- tree copy = build_call_expr (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
3, dest_addr, addr, size_int (rsize));
TREE_ADDRESSABLE (tmp) = 1;
gimplify_and_add (copy, pre_p);
@@ -9236,6 +9361,12 @@ sparc_vis_init_builtins (void)
void_type_node, 0);
tree void_ftype_si = build_function_type_list (void_type_node,
intSI_type_node, 0);
+ tree sf_ftype_sf_sf = build_function_type_list (float_type_node,
+ float_type_node,
+ float_type_node, 0);
+ tree df_ftype_df_df = build_function_type_list (double_type_node,
+ double_type_node,
+ double_type_node, 0);
/* Packing and expanding vectors. */
def_builtin ("__builtin_vis_fpack16", CODE_FOR_fpack16_vis,
@@ -9272,7 +9403,7 @@ sparc_vis_init_builtins (void)
v8qi_ftype_v8qi_v8qi);
def_builtin ("__builtin_vis_faligndatav2si", CODE_FOR_faligndatav2si_vis,
v2si_ftype_v2si_v2si);
- def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatadi_vis,
+ def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatav1di_vis,
di_ftype_di_di);
def_builtin ("__builtin_vis_write_gsr", CODE_FOR_wrgsr_vis,
@@ -9408,7 +9539,7 @@ sparc_vis_init_builtins (void)
v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpadd32", CODE_FOR_addv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpadd32s", CODE_FOR_addsi3,
+ def_builtin_const ("__builtin_vis_fpadd32s", CODE_FOR_addv1si3,
v1si_ftype_v1si_v1si);
def_builtin_const ("__builtin_vis_fpsub16", CODE_FOR_subv4hi3,
v4hi_ftype_v4hi_v4hi);
@@ -9416,7 +9547,7 @@ sparc_vis_init_builtins (void)
v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpsub32", CODE_FOR_subv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpsub32s", CODE_FOR_subsi3,
+ def_builtin_const ("__builtin_vis_fpsub32s", CODE_FOR_subv1si3,
v1si_ftype_v1si_v1si);
/* Three-dimensional array addressing. */
@@ -9454,7 +9585,7 @@ sparc_vis_init_builtins (void)
v8qi_ftype_v8qi_v8qi);
def_builtin ("__builtin_vis_bshufflev2si", CODE_FOR_bshufflev2si_vis,
v2si_ftype_v2si_v2si);
- def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshuffledi_vis,
+ def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshufflev1di_vis,
di_ftype_di_di);
}
@@ -9482,21 +9613,21 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_fchksm16", CODE_FOR_fchksm16_vis,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_fsll16_vis,
+ def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_vashlv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_fslas16_vis,
+ def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_vssashlv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_fsrl16_vis,
+ def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_vlshrv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_fsra16_vis,
+ def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_vashrv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_fsll32_vis,
+ def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_vashlv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_fslas32_vis,
+ def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_vssashlv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_fsrl32_vis,
+ def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_vlshrv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_fsra32_vis,
+ def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_vashrv2si3,
v2si_ftype_v2si_v2si);
if (TARGET_ARCH64)
@@ -9513,21 +9644,21 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_fpsub64", CODE_FOR_fpsub64_vis,
di_ftype_di_di);
- def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_fpadds16_vis,
+ def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_ssaddv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_fpadds16s_vis,
+ def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_ssaddv2hi3,
v2hi_ftype_v2hi_v2hi);
- def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_fpsubs16_vis,
+ def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_sssubv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_fpsubs16s_vis,
+ def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_sssubv2hi3,
v2hi_ftype_v2hi_v2hi);
- def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_fpadds32_vis,
+ def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_ssaddv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_fpadds32s_vis,
+ def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_ssaddv1si3,
v1si_ftype_v1si_v1si);
- def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_fpsubs32_vis,
+ def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_sssubv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_fpsubs32s_vis,
+ def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_sssubv1si3,
v1si_ftype_v1si_v1si);
if (TARGET_ARCH64)
@@ -9552,6 +9683,26 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8si_vis,
si_ftype_v8qi_v8qi);
}
+
+ def_builtin_const ("__builtin_vis_fhadds", CODE_FOR_fhaddsf_vis,
+ sf_ftype_sf_sf);
+ def_builtin_const ("__builtin_vis_fhaddd", CODE_FOR_fhadddf_vis,
+ df_ftype_df_df);
+ def_builtin_const ("__builtin_vis_fhsubs", CODE_FOR_fhsubsf_vis,
+ sf_ftype_sf_sf);
+ def_builtin_const ("__builtin_vis_fhsubd", CODE_FOR_fhsubdf_vis,
+ df_ftype_df_df);
+ def_builtin_const ("__builtin_vis_fnhadds", CODE_FOR_fnhaddsf_vis,
+ sf_ftype_sf_sf);
+ def_builtin_const ("__builtin_vis_fnhaddd", CODE_FOR_fnhadddf_vis,
+ df_ftype_df_df);
+
+ def_builtin_const ("__builtin_vis_umulxhi", CODE_FOR_umulxhi_vis,
+ di_ftype_di_di);
+ def_builtin_const ("__builtin_vis_xmulx", CODE_FOR_xmulx_vis,
+ di_ftype_di_di);
+ def_builtin_const ("__builtin_vis_xmulxhi", CODE_FOR_xmulxhi_vis,
+ di_ftype_di_di);
}
}
@@ -9597,6 +9748,13 @@ sparc_expand_builtin (tree exp, rtx target,
insn_op = &insn_data[icode].operand[idx];
op[arg_count] = expand_normal (arg);
+ if (insn_op->mode == V1DImode
+ && GET_MODE (op[arg_count]) == DImode)
+ op[arg_count] = gen_lowpart (V1DImode, op[arg_count]);
+ else if (insn_op->mode == V1SImode
+ && GET_MODE (op[arg_count]) == SImode)
+ op[arg_count] = gen_lowpart (V1SImode, op[arg_count]);
+
if (! (*insn_data[icode].operand[idx].predicate) (op[arg_count],
insn_op->mode))
op[arg_count] = copy_to_mode_reg (insn_op->mode, op[arg_count]);
@@ -9716,24 +9874,23 @@ sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
if (ignore)
{
- switch (icode)
- {
- case CODE_FOR_alignaddrsi_vis:
- case CODE_FOR_alignaddrdi_vis:
- case CODE_FOR_wrgsr_vis:
- case CODE_FOR_bmasksi_vis:
- case CODE_FOR_bmaskdi_vis:
- case CODE_FOR_cmask8si_vis:
- case CODE_FOR_cmask8di_vis:
- case CODE_FOR_cmask16si_vis:
- case CODE_FOR_cmask16di_vis:
- case CODE_FOR_cmask32si_vis:
- case CODE_FOR_cmask32di_vis:
- break;
-
- default:
- return build_zero_cst (rtype);
- }
+ /* Note that a switch statement instead of the sequence of tests would
+ be incorrect as many of the CODE_FOR values could be CODE_FOR_nothing
+ and that would yield multiple alternatives with identical values. */
+ if (icode == CODE_FOR_alignaddrsi_vis
+ || icode == CODE_FOR_alignaddrdi_vis
+ || icode == CODE_FOR_wrgsr_vis
+ || icode == CODE_FOR_bmasksi_vis
+ || icode == CODE_FOR_bmaskdi_vis
+ || icode == CODE_FOR_cmask8si_vis
+ || icode == CODE_FOR_cmask8di_vis
+ || icode == CODE_FOR_cmask16si_vis
+ || icode == CODE_FOR_cmask16di_vis
+ || icode == CODE_FOR_cmask32si_vis
+ || icode == CODE_FOR_cmask32di_vis)
+ ;
+ else
+ return build_zero_cst (rtype);
}
switch (icode)
@@ -10360,6 +10517,104 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
return (vcall_offset >= -32768 || ! fixed_regs[5]);
}
+/* We use the machine specific reorg pass to enable workarounds for errata. */
+
+static void
+sparc_reorg (void)
+{
+ rtx insn, next;
+
+ /* The only erratum we handle for now is that of the AT697F processor. */
+ if (!sparc_fix_at697f)
+ return;
+
+ /* We need to have the (essentially) final form of the insn stream in order
+ to properly detect the various hazards. Run delay slot scheduling. */
+ if (optimize > 0 && flag_delayed_branch)
+ dbr_schedule (get_insns ());
+
+ /* Now look for specific patterns in the insn stream. */
+ for (insn = get_insns (); insn; insn = next)
+ {
+ bool insert_nop = false;
+ rtx set;
+
+ /* Look for a single-word load into an odd-numbered FP register. */
+ if (NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+ && MEM_P (SET_SRC (set))
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) > 31
+ && REGNO (SET_DEST (set)) % 2 != 0)
+ {
+ /* The wrong dependency is on the enclosing double register. */
+ unsigned int x = REGNO (SET_DEST (set)) - 1;
+ unsigned int src1, src2, dest;
+ int code;
+
+ /* If the insn has a delay slot, then it cannot be problematic. */
+ next = next_active_insn (insn);
+ if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+ code = -1;
+ else
+ {
+ extract_insn (next);
+ code = INSN_CODE (next);
+ }
+
+ switch (code)
+ {
+ case CODE_FOR_adddf3:
+ case CODE_FOR_subdf3:
+ case CODE_FOR_muldf3:
+ case CODE_FOR_divdf3:
+ dest = REGNO (recog_data.operand[0]);
+ src1 = REGNO (recog_data.operand[1]);
+ src2 = REGNO (recog_data.operand[2]);
+ if (src1 != src2)
+ {
+ /* Case [1-4]:
+ ld [address], %fx+1
+ FPOPd %f{x,y}, %f{y,x}, %f{x,y} */
+ if ((src1 == x || src2 == x)
+ && (dest == src1 || dest == src2))
+ insert_nop = true;
+ }
+ else
+ {
+ /* Case 5:
+ ld [address], %fx+1
+ FPOPd %fx, %fx, %fx */
+ if (src1 == x
+ && dest == src1
+ && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
+ insert_nop = true;
+ }
+ break;
+
+ case CODE_FOR_sqrtdf2:
+ dest = REGNO (recog_data.operand[0]);
+ src1 = REGNO (recog_data.operand[1]);
+ /* Case 6:
+ ld [address], %fx+1
+ fsqrtd %fx, %fx */
+ if (src1 == x && dest == src1)
+ insert_nop = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ next = NEXT_INSN (insn);
+
+ if (insert_nop)
+ emit_insn_after (gen_nop (), insn);
+ }
+}
+
/* How to allocate a 'struct machine_function'. */
static struct machine_function *
@@ -10608,6 +10863,113 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
}
+void
+sparc_expand_vec_perm_bmask (enum machine_mode vmode, rtx sel)
+{
+ rtx t_1, t_2, t_3;
+
+ sel = gen_lowpart (DImode, sel);
+ switch (vmode)
+ {
+ case V2SImode:
+ /* inp = xxxxxxxAxxxxxxxB */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ....xxxxxxxAxxx. */
+ sel = expand_simple_binop (SImode, AND, gen_lowpart (SImode, sel),
+ GEN_INT (3), NULL_RTX, 1, OPTAB_DIRECT);
+ t_1 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_1),
+ GEN_INT (0x30000), NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .......B */
+ /* t_1 = ...A.... */
+ sel = expand_simple_binop (SImode, IOR, sel, t_1, sel, 1, OPTAB_DIRECT);
+ /* sel = ...A...B */
+ sel = expand_mult (SImode, sel, GEN_INT (0x4444), sel, 1);
+ /* sel = AAAABBBB * 4 */
+ t_1 = force_reg (SImode, GEN_INT (0x01230123));
+ /* sel = { A*4, A*4+1, A*4+2, ... } */
+ break;
+
+ case V4HImode:
+ /* inp = xxxAxxxBxxxCxxxD */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (8),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_2 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_3 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (24),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ..xxxAxxxBxxxCxx */
+ /* t_2 = ....xxxAxxxBxxxC */
+ /* t_3 = ......xxxAxxxBxx */
+ sel = expand_simple_binop (SImode, AND, gen_lowpart (SImode, sel),
+ GEN_INT (0x07),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_1 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_1),
+ GEN_INT (0x0700),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_2 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_2),
+ GEN_INT (0x070000),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_3 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_3),
+ GEN_INT (0x07000000),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .......D */
+ /* t_1 = .....C.. */
+ /* t_2 = ...B.... */
+ /* t_3 = .A...... */
+ sel = expand_simple_binop (SImode, IOR, sel, t_1, sel, 1, OPTAB_DIRECT);
+ t_2 = expand_simple_binop (SImode, IOR, t_2, t_3, t_2, 1, OPTAB_DIRECT);
+ sel = expand_simple_binop (SImode, IOR, sel, t_2, sel, 1, OPTAB_DIRECT);
+ /* sel = .A.B.C.D */
+ sel = expand_mult (SImode, sel, GEN_INT (0x22), sel, 1);
+ /* sel = AABBCCDD * 2 */
+ t_1 = force_reg (SImode, GEN_INT (0x01010101));
+ /* sel = { A*2, A*2+1, B*2, B*2+1, ... } */
+ break;
+
+ case V8QImode:
+ /* input = xAxBxCxDxExFxGxH */
+ sel = expand_simple_binop (DImode, AND, sel,
+ GEN_INT ((HOST_WIDE_INT)0x0f0f0f0f << 32
+ | 0x0f0f0f0f),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .A.B.C.D.E.F.G.H */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (4),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ..A.B.C.D.E.F.G. */
+ sel = expand_simple_binop (DImode, IOR, sel, t_1,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .AABBCCDDEEFFGGH */
+ sel = expand_simple_binop (DImode, AND, sel,
+ GEN_INT ((HOST_WIDE_INT)0xff00ff << 32
+ | 0xff00ff),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = ..AB..CD..EF..GH */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (8),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ....AB..CD..EF.. */
+ sel = expand_simple_binop (DImode, IOR, sel, t_1,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = ..ABABCDCDEFEFGH */
+ sel = expand_simple_binop (DImode, AND, sel,
+ GEN_INT ((HOST_WIDE_INT)0xffff << 32 | 0xffff),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = ....ABCD....EFGH */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ........ABCD.... */
+ sel = gen_lowpart (SImode, sel);
+ t_1 = gen_lowpart (SImode, t_1);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Always perform the final addition/merge within the bmask insn. */
+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, t_1));
+}
+
/* Implement TARGET_FRAME_POINTER_REQUIRED. */
static bool
@@ -10739,4 +11101,107 @@ sparc_preferred_reload_class (rtx x, reg_class_t rclass)
return rclass;
}
+const char *
+output_v8plus_mult (rtx insn, rtx *operands, const char *name)
+{
+ char mulstr[32];
+
+ gcc_assert (! TARGET_ARCH64);
+
+ if (sparc_check_64 (operands[1], insn) <= 0)
+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
+ if (which_alternative == 1)
+ output_asm_insn ("sllx\t%H1, 32, %H1", operands);
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (which_alternative == 1)
+ {
+ output_asm_insn ("or\t%L1, %H1, %H1", operands);
+ sprintf (mulstr, "%s\t%%H1, %%2, %%L0", name);
+ output_asm_insn (mulstr, operands);
+ return "srlx\t%L0, 32, %H0";
+ }
+ else
+ {
+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
+ output_asm_insn ("or\t%L1, %3, %3", operands);
+ sprintf (mulstr, "%s\t%%3, %%2, %%3", name);
+ output_asm_insn (mulstr, operands);
+ output_asm_insn ("srlx\t%3, 32, %H0", operands);
+ return "mov\t%3, %L0";
+ }
+ }
+ else if (rtx_equal_p (operands[1], operands[2]))
+ {
+ if (which_alternative == 1)
+ {
+ output_asm_insn ("or\t%L1, %H1, %H1", operands);
+ sprintf (mulstr, "%s\t%%H1, %%H1, %%L0", name);
+ output_asm_insn (mulstr, operands);
+ return "srlx\t%L0, 32, %H0";
+ }
+ else
+ {
+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
+ output_asm_insn ("or\t%L1, %3, %3", operands);
+ sprintf (mulstr, "%s\t%%3, %%3, %%3", name);
+ output_asm_insn (mulstr, operands);
+ output_asm_insn ("srlx\t%3, 32, %H0", operands);
+ return "mov\t%3, %L0";
+ }
+ }
+ if (sparc_check_64 (operands[2], insn) <= 0)
+ output_asm_insn ("srl\t%L2, 0, %L2", operands);
+ if (which_alternative == 1)
+ {
+ output_asm_insn ("or\t%L1, %H1, %H1", operands);
+ output_asm_insn ("sllx\t%H2, 32, %L1", operands);
+ output_asm_insn ("or\t%L2, %L1, %L1", operands);
+ sprintf (mulstr, "%s\t%%H1, %%L1, %%L0", name);
+ output_asm_insn (mulstr, operands);
+ return "srlx\t%L0, 32, %H0";
+ }
+ else
+ {
+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
+ output_asm_insn ("sllx\t%H2, 32, %4", operands);
+ output_asm_insn ("or\t%L1, %3, %3", operands);
+ output_asm_insn ("or\t%L2, %4, %4", operands);
+ sprintf (mulstr, "%s\t%%3, %%4, %%3", name);
+ output_asm_insn (mulstr, operands);
+ output_asm_insn ("srlx\t%3, 32, %H0", operands);
+ return "mov\t%3, %L0";
+ }
+}
+
+void
+sparc_expand_vector_init (rtx target, rtx vals)
+{
+ enum machine_mode mode = GET_MODE (target);
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ int n_elts = GET_MODE_NUNITS (mode);
+ int i, n_var = 0;
+ rtx mem;
+
+ for (i = 0; i < n_elts; i++)
+ {
+ rtx x = XVECEXP (vals, 0, i);
+ if (!CONSTANT_P (x))
+ n_var++;
+ }
+
+ if (n_var == 0)
+ {
+ emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
+ return;
+ }
+
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
+ for (i = 0; i < n_elts; i++)
+ emit_move_insn (adjust_address_nv (mem, inner_mode,
+ i * GET_MODE_SIZE (inner_mode)),
+ XVECEXP (vals, 0, i));
+ emit_move_insn (target, mem);
+}
+
#include "gt-sparc.h"
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index fa943877550..e0db816c9e0 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1608,6 +1608,11 @@ do { \
is done just by pretending it is already truncated. */
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+/* For SImode, we make sure the top 32-bits of the register are clear and
+ then we subtract 32 from the lzd instruction result. */
+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
+ ((VALUE) = ((MODE) == SImode ? 32 : 64), 1)
+
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
@@ -1866,10 +1871,6 @@ extern int sparc_indent_opcode;
#ifndef HAVE_AS_FMAF_HPC_VIS3
#define AS_NIAGARA3_FLAG "b"
-#undef TARGET_FMAF
-#define TARGET_FMAF 0
-#undef TARGET_VIS3
-#define TARGET_VIS3 0
#else
#define AS_NIAGARA3_FLAG "d"
#endif
@@ -1879,3 +1880,9 @@ extern int sparc_indent_opcode;
/* We use gcc _mcount for profiling. */
#define NO_PROFILE_COUNTERS 0
+
+/* Debug support */
+#define MASK_DEBUG_OPTIONS 0x01 /* debug option handling */
+#define MASK_DEBUG_ALL MASK_DEBUG_OPTIONS
+
+#define TARGET_DEBUG_OPTIONS (sparc_debug & MASK_DEBUG_OPTIONS)
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 03158c7f07c..f53bddd080e 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -53,7 +53,7 @@
(UNSPEC_FPACK32 41)
(UNSPEC_FPACKFIX 42)
(UNSPEC_FEXPAND 43)
- (UNSPEC_FPMERGE 44)
+ (UNSPEC_MUL16AU 44)
(UNSPEC_MUL16AL 45)
(UNSPEC_MUL8UL 46)
(UNSPEC_MULDUL 47)
@@ -86,6 +86,12 @@
(UNSPEC_FCHKSM16 80)
(UNSPEC_PDISTN 81)
(UNSPEC_FUCMP 82)
+ (UNSPEC_FHADD 83)
+ (UNSPEC_FHSUB 84)
+ (UNSPEC_XMUL 85)
+ (UNSPEC_MUL8 86)
+ (UNSPEC_MUL8SU 87)
+ (UNSPEC_MULDSU 88)
])
(define_constants
@@ -194,24 +200,12 @@
(define_mode_iterator I [QI HI SI DI])
(define_mode_iterator F [SF DF TF])
-;; We don't define V1SI because SI should work just fine.
-(define_mode_iterator V32 [SF V2HI V4QI])
-(define_mode_iterator V32I [SI V2HI V4QI])
-
-(define_mode_iterator V64 [DF V2SI V4HI V8QI])
-(define_mode_iterator V64I [DI V2SI V4HI V8QI])
-
-(define_mode_iterator V64N8 [V2SI V4HI])
-
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
-(define_mode_attr vbits [(V2SI "32") (V4HI "16") (SI "32s") (V2HI "16s")])
-(define_mode_attr vconstr [(V2SI "e") (V4HI "e") (SI "f") (V2HI "f")])
-
;; Attribute for cpu type.
;; These must match the values for enum processor_type in sparc.h.
(define_attr "cpu"
@@ -392,15 +386,15 @@
(define_attr "in_call_delay" "false,true"
(cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
- (const_string "false")
+ (const_string "false")
(eq_attr "type" "load,fpload,store,fpstore")
- (if_then_else (eq_attr "length" "1")
+ (if_then_else (eq_attr "length" "1")
(const_string "true")
(const_string "false"))]
- (if_then_else (and (eq_attr "length" "1")
- (eq_attr "tls_call_delay" "true"))
- (const_string "true")
- (const_string "false"))))
+ (if_then_else (and (eq_attr "length" "1")
+ (eq_attr "tls_call_delay" "true"))
+ (const_string "true")
+ (const_string "false"))))
(define_attr "eligible_for_sibcall_delay" "false,true"
(symbol_ref "(eligible_for_sibcall_delay (insn)
@@ -1923,24 +1917,23 @@
})
-;; Floating point and vector move instructions
+;; Floating point move instructions
-;; Yes, you guessed it right, the former movsf expander.
-(define_expand "mov<V32:mode>"
- [(set (match_operand:V32 0 "nonimmediate_operand" "")
- (match_operand:V32 1 "general_operand" ""))]
- "<V32:MODE>mode == SFmode || TARGET_VIS"
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
{
- if (sparc_expand_move (<V32:MODE>mode, operands))
+ if (sparc_expand_move (SFmode, operands))
DONE;
})
(define_insn "*movsf_insn"
- [(set (match_operand:V32 0 "nonimmediate_operand" "=d,d,f,*r,*r,*r,f,*r,m,m")
- (match_operand:V32 1 "input_operand" "GY,ZC,f,*rRY,Q,S,m,m,f,*rGY"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d, d,f, *r,*r,*r,f,*r,m, m")
+ (match_operand:SF 1 "input_operand" "GY,ZC,f,*rRY, Q, S,m, m,f,*rGY"))]
"TARGET_FPU
- && (register_operand (operands[0], <V32:MODE>mode)
- || register_or_zero_or_all_ones_operand (operands[1], <V32:MODE>mode))"
+ && (register_operand (operands[0], SFmode)
+ || register_or_zero_or_all_ones_operand (operands[1], SFmode))"
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& (which_alternative == 3
@@ -2061,20 +2054,19 @@
[(set (match_dup 0) (high:SF (match_dup 1)))
(set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
-;; Yes, you again guessed it right, the former movdf expander.
-(define_expand "mov<V64:mode>"
- [(set (match_operand:V64 0 "nonimmediate_operand" "")
- (match_operand:V64 1 "general_operand" ""))]
- "<V64:MODE>mode == DFmode || TARGET_VIS"
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
{
- if (sparc_expand_move (<V64:MODE>mode, operands))
+ if (sparc_expand_move (DFmode, operands))
DONE;
})
;; Be careful, fmovd does not exist when !v9.
(define_insn "*movdf_insn_sp32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
- (match_operand:DF 1 "input_operand" "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e, *r, o, e,o")
+ (match_operand:DF 1 "input_operand" "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
"TARGET_FPU
&& ! TARGET_V9
&& (register_operand (operands[0], DFmode)
@@ -2111,13 +2103,13 @@
;; We have available v9 double floats but not 64-bit integer registers.
(define_insn "*movdf_insn_sp32_v9"
- [(set (match_operand:V64 0 "nonimmediate_operand" "=b,b,e,e,T,W,U,T,f,*r,o")
- (match_operand:V64 1 "input_operand" "GY,ZC,e,W#F,GY,e,T,U,o#F,*roGYDF,*rGYf"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b, b,e, e, T,W,U,T, f, *r, o")
+ (match_operand:DF 1 "input_operand" "GY,ZC,e,W#F,GY,e,T,U,o#F,*roGYDF,*rGYf"))]
"TARGET_FPU
&& TARGET_V9
&& ! TARGET_ARCH64
- && (register_operand (operands[0], <V64:MODE>mode)
- || register_or_zero_or_all_ones_operand (operands[1], <V64:MODE>mode))"
+ && (register_operand (operands[0], DFmode)
+ || register_or_zero_or_all_ones_operand (operands[1], DFmode))"
"@
fzero\t%0
fone\t%0
@@ -2153,12 +2145,12 @@
;; We have available both v9 double floats and 64-bit integer registers.
(define_insn "*movdf_insn_sp64"
- [(set (match_operand:V64 0 "nonimmediate_operand" "=b,b,e,e,W,*r,*r,m,*r")
- (match_operand:V64 1 "input_operand" "GY,ZC,e,W#F,e,*rGY,m,*rGY,DF"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b, b,e, e,W, *r,*r, m,*r")
+ (match_operand:DF 1 "input_operand" "GY,ZC,e,W#F,e,*rGY, m,*rGY,DF"))]
"TARGET_FPU
&& TARGET_ARCH64
- && (register_operand (operands[0], <V64:MODE>mode)
- || register_or_zero_or_all_ones_operand (operands[1], <V64:MODE>mode))"
+ && (register_operand (operands[0], DFmode)
+ || register_or_zero_or_all_ones_operand (operands[1], DFmode))"
"@
fzero\t%0
fone\t%0
@@ -2186,10 +2178,10 @@
stx\t%r1, %0"
[(set_attr "type" "*,load,store")])
-;; This pattern builds V64mode constants in integer registers.
+;; This pattern builds DFmode constants in integer registers.
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "const_double_or_vector_operand" ""))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_double_operand" ""))]
"TARGET_FPU
&& (GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
@@ -2243,8 +2235,8 @@
;; careful when V9 but not ARCH64 because the integer
;; register DFmode cases must be handled.
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "register_operand" ""))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "register_operand" ""))]
"(! TARGET_V9
|| (! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
@@ -2259,18 +2251,11 @@
rtx set_src = operands[1];
rtx dest1, dest2;
rtx src1, src2;
- enum machine_mode half_mode;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- dest1 = gen_highpart (half_mode, set_dest);
- dest2 = gen_lowpart (half_mode, set_dest);
- src1 = gen_highpart (half_mode, set_src);
- src2 = gen_lowpart (half_mode, set_src);
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ src1 = gen_highpart (SFmode, set_src);
+ src2 = gen_lowpart (SFmode, set_src);
/* Now emit using the real source and destination we found, swapping
the order if we detect overlap. */
@@ -2288,8 +2273,8 @@
})
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "memory_operand" ""))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "memory_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& (((REGNO (operands[0]) % 2) != 0)
@@ -2297,34 +2282,27 @@
&& offsettable_memref_p (operands[1])"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx word0, word1;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- word0 = adjust_address (operands[1], half_mode, 0);
- word1 = adjust_address (operands[1], half_mode, 4);
+ word0 = adjust_address (operands[1], SFmode, 0);
+ word1 = adjust_address (operands[1], SFmode, 4);
- if (reg_overlap_mentioned_p (gen_highpart (half_mode, operands[0]), word1))
+ if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
{
- emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
- emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
+ emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), word1);
+ emit_move_insn_1 (gen_highpart (SFmode, operands[0]), word0);
}
else
{
- emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
- emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
+ emit_move_insn_1 (gen_highpart (SFmode, operands[0]), word0);
+ emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), word1);
}
DONE;
})
(define_split
- [(set (match_operand:V64 0 "memory_operand" "")
- (match_operand:V64 1 "register_operand" ""))]
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "register_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& (((REGNO (operands[1]) % 2) != 0)
@@ -2332,26 +2310,19 @@
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx word0, word1;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- word0 = adjust_address (operands[0], half_mode, 0);
- word1 = adjust_address (operands[0], half_mode, 4);
+ word0 = adjust_address (operands[0], SFmode, 0);
+ word1 = adjust_address (operands[0], SFmode, 4);
- emit_move_insn_1 (word0, gen_highpart (half_mode, operands[1]));
- emit_move_insn_1 (word1, gen_lowpart (half_mode, operands[1]));
+ emit_move_insn_1 (word0, gen_highpart (SFmode, operands[1]));
+ emit_move_insn_1 (word1, gen_lowpart (SFmode, operands[1]));
DONE;
})
(define_split
- [(set (match_operand:V64 0 "memory_operand" "")
- (match_operand:V64 1 "const_zero_operand" ""))]
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "const_zero_operand" ""))]
"reload_completed
&& (! TARGET_V9
|| (! TARGET_ARCH64
@@ -2359,26 +2330,19 @@
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx dest1, dest2;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- dest1 = adjust_address (operands[0], half_mode, 0);
- dest2 = adjust_address (operands[0], half_mode, 4);
+ dest1 = adjust_address (operands[0], SFmode, 0);
+ dest2 = adjust_address (operands[0], SFmode, 4);
- emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
- emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
+ emit_move_insn_1 (dest1, CONST0_RTX (SFmode));
+ emit_move_insn_1 (dest2, CONST0_RTX (SFmode));
DONE;
})
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "const_zero_operand" ""))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_zero_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
@@ -2388,20 +2352,13 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx set_dest = operands[0];
rtx dest1, dest2;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- dest1 = gen_highpart (half_mode, set_dest);
- dest2 = gen_lowpart (half_mode, set_dest);
- emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
- emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ emit_move_insn_1 (dest1, CONST0_RTX (SFmode));
+ emit_move_insn_1 (dest2, CONST0_RTX (SFmode));
DONE;
})
@@ -2611,11 +2568,9 @@
(match_operand:I 3 "arith10_operand" "")))]
"TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
{
- enum rtx_code code = GET_CODE (operands[1]);
rtx cc_reg;
- if (GET_MODE (XEXP (operands[1], 0)) == DImode
- && ! TARGET_ARCH64)
+ if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
FAIL;
if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
@@ -2626,12 +2581,14 @@
if (XEXP (operands[1], 1) == const0_rtx
&& GET_CODE (XEXP (operands[1], 0)) == REG
&& GET_MODE (XEXP (operands[1], 0)) == DImode
- && v9_regcmp_p (code))
+ && v9_regcmp_p (GET_CODE (operands[1])))
cc_reg = XEXP (operands[1], 0);
else
cc_reg = gen_compare_reg (operands[1]);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+ operands[1]
+ = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
+ const0_rtx);
})
(define_expand "mov<F:mode>cc"
@@ -2641,11 +2598,9 @@
(match_operand:F 3 "register_operand" "")))]
"TARGET_V9 && TARGET_FPU"
{
- enum rtx_code code = GET_CODE (operands[1]);
rtx cc_reg;
- if (GET_MODE (XEXP (operands[1], 0)) == DImode
- && ! TARGET_ARCH64)
+ if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
FAIL;
if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
@@ -2656,12 +2611,14 @@
if (XEXP (operands[1], 1) == const0_rtx
&& GET_CODE (XEXP (operands[1], 0)) == REG
&& GET_MODE (XEXP (operands[1], 0)) == DImode
- && v9_regcmp_p (code))
+ && v9_regcmp_p (GET_CODE (operands[1])))
cc_reg = XEXP (operands[1], 0);
else
cc_reg = gen_compare_reg (operands[1]);
- operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+ operands[1]
+ = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
+ const0_rtx);
})
;; Conditional move define_insns
@@ -3745,16 +3702,15 @@
sub\t%1, -%2, %0")
(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,d")
- (plus:SI (match_operand:SI 1 "register_operand" "%r,r,d")
- (match_operand:SI 2 "arith_add_operand" "rI,O,d")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
+ (match_operand:SI 2 "arith_add_operand" "rI,O")))]
""
"@
add\t%1, %2, %0
- sub\t%1, -%2, %0
- fpadd32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fga")
- (set_attr "fptype" "*,*,single")])
+ sub\t%1, -%2, %0"
+ [(set_attr "type" "*,*")
+ (set_attr "fptype" "*,*")])
(define_insn "*cmp_cc_plus"
[(set (reg:CC_NOOV CC_REG)
@@ -3917,16 +3873,15 @@
add\t%1, -%2, %0")
(define_insn "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,d")
- (minus:SI (match_operand:SI 1 "register_operand" "r,r,d")
- (match_operand:SI 2 "arith_add_operand" "rI,O,d")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "arith_add_operand" "rI,O")))]
""
"@
sub\t%1, %2, %0
- add\t%1, -%2, %0
- fpsub32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fga")
- (set_attr "fptype" "*,*,single")])
+ add\t%1, -%2, %0"
+ [(set_attr "type" "*,*")
+ (set_attr "fptype" "*,*")])
(define_insn "*cmp_minus_cc"
[(set (reg:CC_NOOV CC_REG)
@@ -4012,32 +3967,7 @@
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_V8PLUS"
-{
- if (sparc_check_64 (operands[1], insn) <= 0)
- output_asm_insn ("srl\t%L1, 0, %L1", operands);
- if (which_alternative == 1)
- output_asm_insn ("sllx\t%H1, 32, %H1", operands);
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (which_alternative == 1)
- return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %2, %L0\;srlx\t%L0, 32, %H0";
- else
- return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
- }
- else if (rtx_equal_p (operands[1], operands[2]))
- {
- if (which_alternative == 1)
- return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %H1, %L0\;srlx\t%L0, 32, %H0";
- else
- return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %3, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
- }
- if (sparc_check_64 (operands[2], insn) <= 0)
- output_asm_insn ("srl\t%L2, 0, %L2", operands);
- if (which_alternative == 1)
- return "or\t%L1, %H1, %H1\n\tsllx\t%H2, 32, %L1\n\tor\t%L2, %L1, %L1\n\tmulx\t%H1, %L1, %L0\;srlx\t%L0, 32, %H0";
- else
- return "sllx\t%H1, 32, %3\n\tsllx\t%H2, 32, %4\n\tor\t%L1, %3, %3\n\tor\t%L2, %4, %4\n\tmulx\t%3, %4, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
-}
+ "* return output_v8plus_mult (insn, operands, \"mulx\");"
[(set_attr "type" "multi")
(set_attr "length" "9,8")])
@@ -4676,46 +4606,33 @@
;; We define DImode `and' so with DImode `not' we can get
;; DImode `andn'. Other combinations are possible.
-(define_expand "and<V64I:mode>3"
- [(set (match_operand:V64I 0 "register_operand" "")
- (and:V64I (match_operand:V64I 1 "arith_double_operand" "")
- (match_operand:V64I 2 "arith_double_operand" "")))]
+(define_expand "anddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*and<V64I:mode>3_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
- (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*anddi3_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))]
"! TARGET_ARCH64"
- "@
- #
- fand\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*and<V64I:mode>3_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (match_operand:V64I 1 "arith_operand" "%r,b")
- (match_operand:V64I 2 "arith_operand" "rI,b")))]
+ "#")
+
+(define_insn "*anddi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- and\t%1, %2, %0
- fand\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "and\t%1, %2, %0")
-(define_insn "and<V32I:mode>3"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (and:V32I (match_operand:V32I 1 "arith_operand" "%r,d")
- (match_operand:V32I 2 "arith_operand" "rI,d")))]
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
""
- "@
- and\t%1, %2, %0
- fands\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "and\t%1, %2, %0")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4729,14 +4646,12 @@
operands[4] = GEN_INT (~INTVAL (operands[2]));
})
-(define_insn_and_split "*and_not_<V64I:mode>_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (not:V64I (match_operand:V64I 1 "register_operand" "%r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+(define_insn_and_split "*and_not_di_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "%r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"! TARGET_ARCH64"
- "@
- #
- fandnot1\t%1, %2, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
@@ -4751,72 +4666,50 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*and_not_<V64I:mode>_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (not:V64I (match_operand:V64I 1 "register_operand" "%r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+ [(set_attr "length" "2")])
+
+(define_insn "*and_not_di_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "%r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_ARCH64"
- "@
- andn\t%2, %1, %0
- fandnot1\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "andn\t%2, %1, %0")
-(define_insn "*and_not_<V32I:mode>"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (and:V32I (not:V32I (match_operand:V32I 1 "register_operand" "%r,d"))
- (match_operand:V32I 2 "register_operand" "r,d")))]
+(define_insn "*and_not_si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
+ (match_operand:SI 2 "register_operand" "r")))]
""
- "@
- andn\t%2, %1, %0
- fandnot1s\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "andn\t%2, %1, %0")
-(define_expand "ior<V64I:mode>3"
- [(set (match_operand:V64I 0 "register_operand" "")
- (ior:V64I (match_operand:V64I 1 "arith_double_operand" "")
- (match_operand:V64I 2 "arith_double_operand" "")))]
+(define_expand "iordi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ior:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*ior<V64I:mode>3_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
- (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*iordi3_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))]
"! TARGET_ARCH64"
- "@
- #
- for\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*ior<V64I:mode>3_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (match_operand:V64I 1 "arith_operand" "%r,b")
- (match_operand:V64I 2 "arith_operand" "rI,b")))]
+ "#"
+ [(set_attr "length" "2")])
+
+(define_insn "*iordi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- or\t%1, %2, %0
- for\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "or\t%1, %2, %0")
-(define_insn "ior<V32I:mode>3"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (ior:V32I (match_operand:V32I 1 "arith_operand" "%r,d")
- (match_operand:V32I 2 "arith_operand" "rI,d")))]
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
""
- "@
- or\t%1, %2, %0
- fors\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "or\t%1, %2, %0")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4830,14 +4723,12 @@
operands[4] = GEN_INT (~INTVAL (operands[2]));
})
-(define_insn_and_split "*or_not_<V64I:mode>_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (not:V64I (match_operand:V64I 1 "register_operand" "r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+(define_insn_and_split "*or_not_di_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"! TARGET_ARCH64"
- "@
- #
- fornot1\t%1, %2, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
@@ -4852,72 +4743,50 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*or_not_<V64I:mode>_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (not:V64I (match_operand:V64I 1 "register_operand" "r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+ [(set_attr "length" "2")])
+
+(define_insn "*or_not_di_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_ARCH64"
- "@
- orn\t%2, %1, %0
- fornot1\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "orn\t%2, %1, %0")
-(define_insn "*or_not_<V32I:mode>"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (ior:V32I (not:V32I (match_operand:V32I 1 "register_operand" "r,d"))
- (match_operand:V32I 2 "register_operand" "r,d")))]
+(define_insn "*or_not_si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r")))]
""
- "@
- orn\t%2, %1, %0
- fornot1s\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "orn\t%2, %1, %0")
-(define_expand "xor<V64I:mode>3"
- [(set (match_operand:V64I 0 "register_operand" "")
- (xor:V64I (match_operand:V64I 1 "arith_double_operand" "")
- (match_operand:V64I 2 "arith_double_operand" "")))]
+(define_expand "xordi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (xor:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*xor<V64I:mode>3_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (xor:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
- (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*xordi3_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))]
"! TARGET_ARCH64"
- "@
- #
- fxor\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*xor<V64I:mode>3_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (xor:V64I (match_operand:V64I 1 "arith_operand" "%rJ,b")
- (match_operand:V64I 2 "arith_operand" "rI,b")))]
+ "#"
+ [(set_attr "length" "2")])
+
+(define_insn "*xordi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (xor:DI (match_operand:DI 1 "arith_operand" "%rJ")
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- xor\t%r1, %2, %0
- fxor\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "xor\t%r1, %2, %0")
-(define_insn "xor<V32I:mode>3"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (xor:V32I (match_operand:V32I 1 "arith_operand" "%rJ,d")
- (match_operand:V32I 2 "arith_operand" "rI,d")))]
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
+ (match_operand:SI 2 "arith_operand" "rI")))]
""
- "@
- xor\t%r1, %2, %0
- fxors\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "xor\t%r1, %2, %0")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4945,10 +4814,10 @@
;; Split DImode logical operations requiring two instructions.
(define_split
- [(set (match_operand:V64I 0 "register_operand" "")
- (match_operator:V64I 1 "cc_arith_operator" ; AND, IOR, XOR
- [(match_operand:V64I 2 "register_operand" "")
- (match_operand:V64I 3 "arith_double_operand" "")]))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operator:DI 1 "cc_arith_operator" ; AND, IOR, XOR
+ [(match_operand:DI 2 "register_operand" "")
+ (match_operand:DI 3 "arith_double_operand" "")]))]
"! TARGET_ARCH64
&& reload_completed
&& ((GET_CODE (operands[0]) == REG
@@ -4964,7 +4833,7 @@
operands[6] = gen_highpart (SImode, operands[2]);
operands[7] = gen_lowpart (SImode, operands[2]);
#if HOST_BITS_PER_WIDE_INT == 32
- if (GET_CODE (operands[3]) == CONST_INT && <V64I:MODE>mode == DImode)
+ if (GET_CODE (operands[3]) == CONST_INT)
{
if (INTVAL (operands[3]) < 0)
operands[8] = constm1_rtx;
@@ -4973,20 +4842,18 @@
}
else
#endif
- operands[8] = gen_highpart_mode (SImode, <V64I:MODE>mode, operands[3]);
+ operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
operands[9] = gen_lowpart (SImode, operands[3]);
})
;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
;; Combine now canonicalizes to the rightmost expression.
-(define_insn_and_split "*xor_not_<V64I:mode>_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (xor:V64I (match_operand:V64I 1 "register_operand" "r,b")
- (match_operand:V64I 2 "register_operand" "r,b"))))]
+(define_insn_and_split "*xor_not_di_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r"))))]
"! TARGET_ARCH64"
- "@
- #
- fxnor\t%1, %2, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
@@ -5001,31 +4868,21 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*xor_not_<V64I:mode>_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (xor:V64I (match_operand:V64I 1 "register_or_zero_operand" "rJ,b")
- (match_operand:V64I 2 "arith_operand" "rI,b"))))]
+ [(set_attr "length" "2")])
+
+(define_insn "*xor_not_di_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (xor:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
+ (match_operand:DI 2 "arith_operand" "rI"))))]
"TARGET_ARCH64"
- "@
- xnor\t%r1, %2, %0
- fxnor\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "xnor\t%r1, %2, %0")
-(define_insn "*xor_not_<V32I:mode>"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (not:V32I (xor:V32I (match_operand:V32I 1 "register_or_zero_operand" "rJ,d")
- (match_operand:V32I 2 "arith_operand" "rI,d"))))]
+(define_insn "*xor_not_si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))))]
""
- "@
- xnor\t%r1, %2, %0
- fxnors\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "xnor\t%r1, %2, %0")
;; These correspond to the above in the case where we also (or only)
;; want to set the condition code.
@@ -5263,19 +5120,17 @@
;; We cannot use the "not" pseudo insn because the Sun assembler
;; does not know how to make it work for constants.
-(define_expand "one_cmpl<V64I:mode>2"
- [(set (match_operand:V64I 0 "register_operand" "")
- (not:V64I (match_operand:V64I 1 "register_operand" "")))]
+(define_expand "one_cmpldi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (not:DI (match_operand:DI 1 "register_operand" "")))]
""
"")
-(define_insn_and_split "*one_cmpl<V64I:mode>2_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (match_operand:V64I 1 "register_operand" "r,b")))]
+(define_insn_and_split "*one_cmpldi2_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (match_operand:DI 1 "register_operand" "r")))]
"! TARGET_ARCH64"
- "@
- #
- fnot1\t%1, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
@@ -5288,29 +5143,19 @@
operands[3] = gen_highpart (SImode, operands[1]);
operands[4] = gen_lowpart (SImode, operands[0]);
operands[5] = gen_lowpart (SImode, operands[1]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
+ [(set_attr "length" "2")])
-(define_insn "*one_cmpl<V64I:mode>2_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (match_operand:V64I 1 "arith_operand" "rI,b")))]
+(define_insn "*one_cmpldi2_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (match_operand:DI 1 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- xnor\t%%g0, %1, %0
- fnot1\t%1, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "xnor\t%%g0, %1, %0")
-(define_insn "one_cmpl<V32I:mode>2"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (not:V32I (match_operand:V32I 1 "arith_operand" "rI,d")))]
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
""
- "@
- xnor\t%%g0, %1, %0
- fnot1s\t%1, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "xnor\t%%g0, %1, %0")
(define_insn "*cmp_cc_not"
[(set (reg:CC CC_REG)
@@ -5814,9 +5659,20 @@
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
return "sll\t%1, %2, %0";
}
- [(set (attr "type")
- (if_then_else (match_operand 2 "const_one_operand" "")
- (const_string "ialu") (const_string "shift")))])
+ [(set_attr "type" "shift")])
+
+(define_insn "*ashlsi3_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI"))))]
+ "TARGET_ARCH64"
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "sll\t%1, %2, %0";
+}
+ [(set_attr "type" "shift")])
(define_expand "ashldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5843,9 +5699,7 @@
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
return "sllx\t%1, %2, %0";
}
- [(set (attr "type")
- (if_then_else (match_operand 2 "const_one_operand" "")
- (const_string "ialu") (const_string "shift")))])
+ [(set_attr "type" "shift")])
;; XXX UGH!
(define_insn "ashldi3_v8plus"
@@ -5980,10 +5834,23 @@
}
[(set_attr "type" "shift")])
+(define_insn "*lshrsi3_extend0"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI"))))]
+ "TARGET_ARCH64"
+ {
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "srl\t%1, %2, %0";
+ }
+ [(set_attr "type" "shift")])
+
;; This handles the case where
;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI))),
;; but combiner "simplifies" it for us.
-(define_insn "*lshrsi3_extend"
+(define_insn "*lshrsi3_extend1"
[(set (match_operand:DI 0 "register_operand" "=r")
(and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "r")) 0)
@@ -6804,21 +6671,142 @@
[(set_attr "type" "multi")
(set_attr "length" "8")])
-;; ??? This should be a define expand, so that the extra instruction have
-;; a chance of being optimized away.
-
-;; Disabled because none of the UltraSPARCs implement popc. The HAL R1
-;; does, but no one uses that and we don't have a switch for it.
-;
-;(define_insn "ffsdi2"
-; [(set (match_operand:DI 0 "register_operand" "=&r")
-; (ffs:DI (match_operand:DI 1 "register_operand" "r")))
-; (clobber (match_scratch:DI 2 "=&r"))]
-; "TARGET_ARCH64"
-; "neg\t%1, %2\;xnor\t%1, %2, %2\;popc\t%2, %0\;movzr\t%1, 0, %0"
-; [(set_attr "type" "multi")
-; (set_attr "length" "4")])
+(define_expand "popcountdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (popcount:DI (match_operand:DI 1 "register_operand" "")))]
+ "TARGET_POPC"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_popcountdi_v8plus (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "*popcountdi_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (popcount:DI (match_operand:DI 1 "register_operand" "r")))]
+ "TARGET_POPC && TARGET_ARCH64"
+ "popc\t%1, %0")
+
+(define_insn "popcountdi_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (popcount:DI (match_operand:DI 1 "register_operand" "r")))
+ (clobber (match_scratch:SI 2 "=&h"))]
+ "TARGET_POPC && ! TARGET_ARCH64"
+{
+ if (sparc_check_64 (operands[1], insn) <= 0)
+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
+ return "sllx\t%H1, 32, %2\n\tor\t%L1, %2, %2\n\tpopc\t%2, %L0\n\tclr\t%H0";
+}
+ [(set_attr "type" "multi")
+ (set_attr "length" "5")])
+
+(define_expand "popcountsi2"
+ [(set (match_dup 2)
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
+ (set (match_operand:SI 0 "register_operand" "")
+ (truncate:SI (popcount:DI (match_dup 2))))]
+ "TARGET_POPC"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_popcountsi_v8plus (operands[0], operands[1]));
+ DONE;
+ }
+ else
+ operands[2] = gen_reg_rtx (DImode);
+})
+
+(define_insn "*popcountsi_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (truncate:SI
+ (popcount:DI (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_POPC && TARGET_ARCH64"
+ "popc\t%1, %0")
+
+(define_insn "popcountsi_v8plus"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (popcount:SI (match_operand:SI 1 "register_operand" "r")))]
+ "TARGET_POPC && ! TARGET_ARCH64"
+{
+ if (sparc_check_64 (operands[1], insn) <= 0)
+ output_asm_insn ("srl\t%1, 0, %1", operands);
+ return "popc\t%1, %0";
+}
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
+
+(define_expand "clzdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (clz:DI (match_operand:DI 1 "register_operand" "")))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_clzdi_v8plus (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "*clzdi_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (clz:DI (match_operand:DI 1 "register_operand" "r")))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "lzd\t%1, %0")
+
+(define_insn "clzdi_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (clz:DI (match_operand:DI 1 "register_operand" "r")))
+ (clobber (match_scratch:SI 2 "=&h"))]
+ "TARGET_VIS3 && ! TARGET_ARCH64"
+{
+ if (sparc_check_64 (operands[1], insn) <= 0)
+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
+ return "sllx\t%H1, 32, %2\n\tor\t%L1, %2, %2\n\tlzd\t%2, %L0\n\tclr\t%H0";
+}
+ [(set_attr "type" "multi")
+ (set_attr "length" "5")])
+
+(define_expand "clzsi2"
+ [(set (match_dup 2)
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
+ (set (match_dup 3)
+ (truncate:SI (clz:DI (match_dup 2))))
+ (set (match_operand:SI 0 "register_operand" "")
+ (minus:SI (match_dup 3) (const_int 32)))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_clzsi_v8plus (operands[0], operands[1]));
+ DONE;
+ }
+ else
+ {
+ operands[2] = gen_reg_rtx (DImode);
+ operands[3] = gen_reg_rtx (SImode);
+ }
+})
+
+(define_insn "*clzsi_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (truncate:SI
+ (clz:DI (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "lzd\t%1, %0")
+(define_insn "clzsi_v8plus"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (clz:SI (match_operand:SI 1 "register_operand" "r")))]
+ "TARGET_VIS3 && ! TARGET_ARCH64"
+{
+ if (sparc_check_64 (operands[1], insn) <= 0)
+ output_asm_insn ("srl\t%1, 0, %1", operands);
+ return "lzd\t%1, %0\n\tsub\t%0, 32, %0";
+}
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
;; Peepholes go at the end.
@@ -7757,97 +7745,203 @@
[(set_attr "type" "multi")
(set_attr "length" "4")])
-
;; Vector instructions.
-(define_insn "addv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=e")
- (plus:V2SI (match_operand:V2SI 1 "register_operand" "e")
- (match_operand:V2SI 2 "register_operand" "e")))]
+(define_mode_iterator VM32 [V1SI V2HI V4QI])
+(define_mode_iterator VM64 [V1DI V2SI V4HI V8QI])
+(define_mode_iterator VMALL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
+
+(define_mode_attr vbits [(V2SI "32") (V4HI "16") (V1SI "32s") (V2HI "16s")])
+(define_mode_attr vconstr [(V1SI "f") (V2HI "f") (V4QI "f")
+ (V1DI "e") (V2SI "e") (V4HI "e") (V8QI "e")])
+(define_mode_attr vfptype [(V1SI "single") (V2HI "single") (V4QI "single")
+ (V1DI "double") (V2SI "double") (V4HI "double")
+ (V8QI "double")])
+
+(define_expand "mov<VMALL:mode>"
+ [(set (match_operand:VMALL 0 "nonimmediate_operand" "")
+ (match_operand:VMALL 1 "general_operand" ""))]
"TARGET_VIS"
- "fpadd32\t%1, %2, %0"
- [(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+{
+ if (sparc_expand_move (<VMALL:MODE>mode, operands))
+ DONE;
+})
-(define_insn "addv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=e")
- (plus:V4HI (match_operand:V4HI 1 "register_operand" "e")
- (match_operand:V4HI 2 "register_operand" "e")))]
+(define_insn "*mov<VM32:mode>_insn"
+ [(set (match_operand:VM32 0 "nonimmediate_operand" "=f, f,f,f,m, m,r,m, r, r")
+ (match_operand:VM32 1 "input_operand" "GY,ZC,f,m,f,GY,m,r,GY,ZC"))]
+ "TARGET_VIS
+ && (register_operand (operands[0], <VM32:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM32:MODE>mode))"
+ "@
+ fzeros\t%0
+ fones\t%0
+ fsrc1s\t%1, %0
+ ld\t%1, %0
+ st\t%1, %0
+ st\t%r1, %0
+ ld\t%1, %0
+ st\t%1, %0
+ mov\t0, %0
+ mov\t-1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*")])
+
+(define_insn "*mov<VM64:mode>_insn_sp64"
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e, e,e,e,m, m,r,m, r, r")
+ (match_operand:VM64 1 "input_operand" "GY,ZC,e,m,e,GY,m,r,GY,ZC"))]
+ "TARGET_VIS
+ && TARGET_ARCH64
+ && (register_operand (operands[0], <VM64:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
+ "@
+ fzero\t%0
+ fone\t%0
+ fsrc1\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
+ ldx\t%1, %0
+ stx\t%1, %0
+ mov\t0, %0
+ mov\t-1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*")])
+
+(define_insn "*mov<VM64:mode>_insn_sp32"
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e, e,e,e,m, m,U,T,o, r, r")
+ (match_operand:VM64 1 "input_operand" "GY,ZC,e,m,e,GY,T,U,r,GY,ZC"))]
+ "TARGET_VIS
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], <VM64:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
+ "@
+ fzero\t%0
+ fone\t%0
+ fsrc1\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ #
+ mov 0, %L0; mov 0, %H0
+ mov -1, %L0; mov -1, %H0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*,*")
+ (set_attr "length" "*,*,*,*,*,*,*,*,2,2,2")])
+
+(define_split
+ [(set (match_operand:VM64 0 "memory_operand" "")
+ (match_operand:VM64 1 "register_operand" ""))]
+ "reload_completed
+ && TARGET_VIS
+ && ! TARGET_ARCH64
+ && (((REGNO (operands[1]) % 2) != 0)
+ || ! mem_min_alignment (operands[0], 8))
+ && offsettable_memref_p (operands[0])"
+ [(clobber (const_int 0))]
+{
+ rtx word0, word1;
+
+ word0 = adjust_address (operands[0], SImode, 0);
+ word1 = adjust_address (operands[0], SImode, 4);
+
+ emit_move_insn_1 (word0, gen_highpart (SImode, operands[1]));
+ emit_move_insn_1 (word1, gen_lowpart (SImode, operands[1]));
+ DONE;
+})
+
+(define_expand "vec_init<mode>"
+ [(match_operand:VMALL 0 "register_operand" "")
+ (match_operand:VMALL 1 "" "")]
"TARGET_VIS"
- "fpadd16\t%1, %2, %0"
- [(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+{
+ sparc_expand_vector_init (operands[0], operands[1]);
+ DONE;
+})
-;; fpadd32s is emitted by the addsi3 pattern.
+(define_code_iterator plusminus [plus minus])
+(define_code_attr plusminus_insn [(plus "add") (minus "sub")])
-(define_insn "addv2hi3"
- [(set (match_operand:V2HI 0 "register_operand" "=f")
- (plus:V2HI (match_operand:V2HI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+(define_mode_iterator VADDSUB [V1SI V2SI V2HI V4HI])
+
+(define_insn "<plusminus_insn><mode>3"
+ [(set (match_operand:VADDSUB 0 "register_operand" "=<vconstr>")
+ (plusminus:VADDSUB (match_operand:VADDSUB 1 "register_operand" "<vconstr>")
+ (match_operand:VADDSUB 2 "register_operand" "<vconstr>")))]
"TARGET_VIS"
- "fpadd16s\t%1, %2, %0"
+ "fp<plusminus_insn><vbits>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "single")])
-
-(define_insn "subv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=e")
- (minus:V2SI (match_operand:V2SI 1 "register_operand" "e")
- (match_operand:V2SI 2 "register_operand" "e")))]
+ (set_attr "fptype" "<vfptype>")])
+
+(define_mode_iterator VL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
+(define_mode_attr vlsuf [(V1SI "s") (V2HI "s") (V4QI "s")
+ (V1DI "") (V2SI "") (V4HI "") (V8QI "")])
+(define_code_iterator vlop [ior and xor])
+(define_code_attr vlinsn [(ior "or") (and "and") (xor "xor")])
+(define_code_attr vlninsn [(ior "nor") (and "nand") (xor "xnor")])
+
+(define_insn "<code><mode>3"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
"TARGET_VIS"
- "fpsub32\t%1, %2, %0"
+ "f<vlinsn><vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "<vfptype>")])
-(define_insn "subv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=e")
- (minus:V4HI (match_operand:V4HI 1 "register_operand" "e")
- (match_operand:V4HI 2 "register_operand" "e")))]
+(define_insn "*not_<code><mode>3"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (not:VL (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (match_operand:VL 2 "register_operand" "<vconstr>"))))]
"TARGET_VIS"
- "fpsub16\t%1, %2, %0"
+ "f<vlninsn><vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "<vfptype>")])
-;; fpsub32s is emitted by the subsi3 pattern.
-
-(define_insn "subv2hi3"
- [(set (match_operand:V2HI 0 "register_operand" "=f")
- (minus:V2HI (match_operand:V2HI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
+(define_insn "*nand<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (ior:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
"TARGET_VIS"
- "fpsub16s\t%1, %2, %0"
+ "fnand<vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "single")])
+ (set_attr "fptype" "<vfptype>")])
-;; All other logical instructions have integer equivalents so they
-;; are defined together.
+(define_code_iterator vlnotop [ior and])
-;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
+(define_insn "*<code>_not1<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlnotop:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS"
+ "f<vlinsn>not1<vlsuf>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
-(define_insn "*nand<V64:mode>_vis"
- [(set (match_operand:V64 0 "register_operand" "=e")
- (ior:V64 (not:V64 (match_operand:V64 1 "register_operand" "e"))
- (not:V64 (match_operand:V64 2 "register_operand" "e"))))]
+(define_insn "*<code>_not2<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlnotop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
"TARGET_VIS"
- "fnand\t%1, %2, %0"
+ "f<vlinsn>not2<vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "<vfptype>")])
-(define_insn "*nand<V32:mode>_vis"
- [(set (match_operand:V32 0 "register_operand" "=f")
- (ior:V32 (not:V32 (match_operand:V32 1 "register_operand" "f"))
- (not:V32 (match_operand:V32 2 "register_operand" "f"))))]
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (not:VL (match_operand:VL 1 "register_operand" "<vconstr>")))]
"TARGET_VIS"
- "fnands\t%1, %2, %0"
+ "fnot1<vlsuf>\t%1, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "single")])
+ (set_attr "fptype" "<vfptype>")])
;; Hard to generate VIS instructions. We have builtins for these.
(define_insn "fpack16_vis"
[(set (match_operand:V4QI 0 "register_operand" "=f")
- (unspec:V4QI [(match_operand:V4HI 1 "register_operand" "e")]
- UNSPEC_FPACK16))
- (use (reg:DI GSR_REG))]
+ (unspec:V4QI [(match_operand:V4HI 1 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_FPACK16))]
"TARGET_VIS"
"fpack16\t%1, %0"
[(set_attr "type" "fga")
@@ -7855,9 +7949,9 @@
(define_insn "fpackfix_vis"
[(set (match_operand:V2HI 0 "register_operand" "=f")
- (unspec:V2HI [(match_operand:V2SI 1 "register_operand" "e")]
- UNSPEC_FPACKFIX))
- (use (reg:DI GSR_REG))]
+ (unspec:V2HI [(match_operand:V2SI 1 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_FPACKFIX))]
"TARGET_VIS"
"fpackfix\t%1, %0"
[(set_attr "type" "fga")
@@ -7866,9 +7960,9 @@
(define_insn "fpack32_vis"
[(set (match_operand:V8QI 0 "register_operand" "=e")
(unspec:V8QI [(match_operand:V2SI 1 "register_operand" "e")
- (match_operand:V8QI 2 "register_operand" "e")]
- UNSPEC_FPACK32))
- (use (reg:DI GSR_REG))]
+ (match_operand:V8QI 2 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_FPACK32))]
"TARGET_VIS"
"fpack32\t%1, %2, %0"
[(set_attr "type" "fga")
@@ -7883,36 +7977,64 @@
[(set_attr "type" "fga")
(set_attr "fptype" "double")])
-;; It may be possible to describe this operation as (1 indexed):
-;; (vec_select (vec_duplicate (vec_duplicate (vec_concat 1 2)))
-;; 1,5,10,14,19,23,28,32)
-;; Note that (vec_merge:V8QI [(V4QI) (V4QI)] (10101010 = 170) doesn't work
-;; because vec_merge expects all the operands to be of the same type.
(define_insn "fpmerge_vis"
[(set (match_operand:V8QI 0 "register_operand" "=e")
- (unspec:V8QI [(match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V4QI 2 "register_operand" "f")]
- UNSPEC_FPMERGE))]
+ (vec_select:V8QI
+ (vec_concat:V8QI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4QI 2 "register_operand" "f"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)
+ (const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
"TARGET_VIS"
"fpmerge\t%1, %2, %0"
[(set_attr "type" "fga")
(set_attr "fptype" "double")])
+(define_insn "vec_interleave_lowv8qi"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (vec_select:V8QI
+ (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
+ (match_operand:V8QI 2 "register_operand" "f"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 1) (const_int 9)
+ (const_int 2) (const_int 10)
+ (const_int 3) (const_int 11)])))]
+ "TARGET_VIS"
+ "fpmerge\t%L1, %L2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "vec_interleave_highv8qi"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (vec_select:V8QI
+ (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
+ (match_operand:V8QI 2 "register_operand" "f"))
+ (parallel [(const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_VIS"
+ "fpmerge\t%H1, %H2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
;; Partitioned multiply instructions
(define_insn "fmul8x16_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
- (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V4HI 2 "register_operand" "e")))]
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8))]
"TARGET_VIS"
"fmul8x16\t%1, %2, %0"
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
-;; Only one of the following two insns can be a multiply.
(define_insn "fmul8x16au_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
- (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MUL16AU))]
"TARGET_VIS"
"fmul8x16au\t%1, %2, %0"
[(set_attr "type" "fpmul")
@@ -7928,11 +8050,11 @@
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
-;; Only one of the following two insns can be a multiply.
(define_insn "fmul8sux16_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
- (mult:V4HI (match_operand:V8QI 1 "register_operand" "e")
- (match_operand:V4HI 2 "register_operand" "e")))]
+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8SU))]
"TARGET_VIS"
"fmul8sux16\t%1, %2, %0"
[(set_attr "type" "fpmul")
@@ -7948,11 +8070,11 @@
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
-;; Only one of the following two insns can be a multiply.
(define_insn "fmuld8sux16_vis"
[(set (match_operand:V2SI 0 "register_operand" "=e")
- (mult:V2SI (match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MULDSU))]
"TARGET_VIS"
"fmuld8sux16\t%1, %2, %0"
[(set_attr "type" "fpmul")
@@ -8028,12 +8150,12 @@
;; Using faligndata only makes sense after an alignaddr since the choice of
;; bytes to take out of each operand is dependent on the results of the last
;; alignaddr.
-(define_insn "faligndata<V64I:mode>_vis"
- [(set (match_operand:V64I 0 "register_operand" "=e")
- (unspec:V64I [(match_operand:V64I 1 "register_operand" "e")
- (match_operand:V64I 2 "register_operand" "e")]
- UNSPEC_ALIGNDATA))
- (use (reg:SI GSR_REG))]
+(define_insn "faligndata<VM64:mode>_vis"
+ [(set (match_operand:VM64 0 "register_operand" "=e")
+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
+ (match_operand:VM64 2 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_ALIGNDATA))]
"TARGET_VIS"
"faligndata\t%1, %2, %0"
[(set_attr "type" "fga")
@@ -8043,10 +8165,8 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
(match_operand:SI 2 "register_or_zero_operand" "rJ")))
- (set (reg:SI GSR_REG)
- (ior:SI (and:SI (reg:SI GSR_REG) (const_int -8))
- (and:SI (plus:SI (match_dup 1) (match_dup 2))
- (const_int 7))))]
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
"TARGET_VIS"
"alignaddr\t%r1, %r2, %0")
@@ -8054,10 +8174,8 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
(match_operand:DI 2 "register_or_zero_operand" "rJ")))
- (set (reg:SI GSR_REG)
- (ior:SI (and:SI (reg:SI GSR_REG) (const_int -8))
- (and:SI (truncate:SI (plus:DI (match_dup 1) (match_dup 2)))
- (const_int 7))))]
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_VIS"
"alignaddr\t%r1, %r2, %0")
@@ -8065,11 +8183,9 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
(match_operand:SI 2 "register_or_zero_operand" "rJ")))
- (set (reg:SI GSR_REG)
- (ior:SI (and:SI (reg:SI GSR_REG) (const_int -8))
- (xor:SI (and:SI (plus:SI (match_dup 1) (match_dup 2))
- (const_int 7))
- (const_int 7))))]
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (xor:DI (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2)))
+ (const_int 7)))]
"TARGET_VIS"
"alignaddrl\t%r1, %r2, %0")
@@ -8077,12 +8193,9 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
(match_operand:DI 2 "register_or_zero_operand" "rJ")))
- (set (reg:SI GSR_REG)
- (ior:SI (and:SI (reg:SI GSR_REG) (const_int -8))
- (xor:SI (and:SI (truncate:SI (plus:DI (match_dup 1)
- (match_dup 2)))
- (const_int 7))
- (const_int 7))))]
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
+ (xor:DI (plus:DI (match_dup 1) (match_dup 2))
+ (const_int 7)))]
"TARGET_VIS"
"alignaddrl\t%r1, %r2, %0")
@@ -8101,8 +8214,8 @@
;; with the same operands.
(define_insn "edge8<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8))]
@@ -8112,8 +8225,8 @@
(define_insn "edge8l<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8L))]
@@ -8123,8 +8236,8 @@
(define_insn "edge16<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16))]
@@ -8134,8 +8247,8 @@
(define_insn "edge16l<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16L))]
@@ -8145,8 +8258,8 @@
(define_insn "edge32<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32))]
@@ -8156,8 +8269,8 @@
(define_insn "edge32l<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32L))]
@@ -8181,8 +8294,8 @@
(define_insn "array8<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_ARRAY8))]
"TARGET_VIS"
"array8\t%r1, %r2, %0"
@@ -8190,8 +8303,8 @@
(define_insn "array16<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_ARRAY16))]
"TARGET_VIS"
"array16\t%r1, %r2, %0"
@@ -8199,38 +8312,86 @@
(define_insn "array32<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_ARRAY32))]
"TARGET_VIS"
"array32\t%r1, %r2, %0"
[(set_attr "type" "array")])
-(define_insn "bmask<P:mode>_vis"
- [(set (match_operand:P 0 "register_operand" "=r")
- (plus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")))
- (clobber (reg:SI GSR_REG))]
+(define_insn "bmaskdi_vis"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
+ (plus:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_VIS2"
+ "bmask\t%r1, %r2, %0"
+ [(set_attr "type" "array")])
+
+(define_insn "bmasksi_vis"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
"TARGET_VIS2"
"bmask\t%r1, %r2, %0"
[(set_attr "type" "array")])
-(define_insn "bshuffle<V64I:mode>_vis"
- [(set (match_operand:V64I 0 "register_operand" "=e")
- (unspec:V64I [(match_operand:V64I 1 "register_operand" "e")
- (match_operand:V64I 2 "register_operand" "e")]
- UNSPEC_BSHUFFLE))
- (use (reg:SI GSR_REG))]
+(define_insn "bshuffle<VM64:mode>_vis"
+ [(set (match_operand:VM64 0 "register_operand" "=e")
+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
+ (match_operand:VM64 2 "register_operand" "e")
+ (reg:DI GSR_REG)]
+ UNSPEC_BSHUFFLE))]
"TARGET_VIS2"
"bshuffle\t%1, %2, %0"
[(set_attr "type" "fga")
(set_attr "fptype" "double")])
+;; The rtl expanders will happily convert constant permutations on other
+;; modes down to V8QI. Rely on this to avoid the complexity of the byte
+;; order of the permutation.
+(define_expand "vec_perm_constv8qi"
+ [(match_operand:V8QI 0 "register_operand" "")
+ (match_operand:V8QI 1 "register_operand" "")
+ (match_operand:V8QI 2 "register_operand" "")
+ (match_operand:V8QI 3 "" "")]
+ "TARGET_VIS2"
+{
+ unsigned int i, mask;
+ rtx sel = operands[3];
+
+ for (i = mask = 0; i < 8; ++i)
+ mask |= (INTVAL (XVECEXP (sel, 0, i)) & 0xf) << (28 - i*4);
+ sel = force_reg (SImode, gen_int_mode (mask, SImode));
+
+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, const0_rtx));
+ emit_insn (gen_bshufflev8qi_vis (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+;; Unlike constant permutation, we can vastly simplify the compression of
+;; the 64-bit selector input to the 32-bit %gsr value by knowing what the
+;; width of the input is.
+(define_expand "vec_perm<mode>"
+ [(match_operand:VM64 0 "register_operand" "")
+ (match_operand:VM64 1 "register_operand" "")
+ (match_operand:VM64 2 "register_operand" "")
+ (match_operand:VM64 3 "register_operand" "")]
+ "TARGET_VIS2"
+{
+ sparc_expand_vec_perm_bmask (<MODE>mode, operands[3]);
+ emit_insn (gen_bshuffle<mode>_vis (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
;; VIS 2.0 adds edge variants which do not set the condition codes
(define_insn "edge8n<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE8N))]
"TARGET_VIS2"
"edge8n\t%r1, %r2, %0"
@@ -8238,8 +8399,8 @@
(define_insn "edge8ln<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE8LN))]
"TARGET_VIS2"
"edge8ln\t%r1, %r2, %0"
@@ -8247,8 +8408,8 @@
(define_insn "edge16n<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE16N))]
"TARGET_VIS2"
"edge16n\t%r1, %r2, %0"
@@ -8256,8 +8417,8 @@
(define_insn "edge16ln<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE16LN))]
"TARGET_VIS2"
"edge16ln\t%r1, %r2, %0"
@@ -8265,8 +8426,8 @@
(define_insn "edge32n<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE32N))]
"TARGET_VIS2"
"edge32n\t%r1, %r2, %0"
@@ -8274,8 +8435,8 @@
(define_insn "edge32ln<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE32LN))]
"TARGET_VIS2"
"edge32ln\t%r1, %r2, %0"
@@ -8317,11 +8478,13 @@
(define_code_iterator vis3_shift [ashift ss_ashift lshiftrt ashiftrt])
(define_code_attr vis3_shift_insn
[(ashift "fsll") (ss_ashift "fslas") (lshiftrt "fsrl") (ashiftrt "fsra")])
+(define_code_attr vis3_shift_patname
+ [(ashift "ashl") (ss_ashift "ssashl") (lshiftrt "lshr") (ashiftrt "ashr")])
-(define_insn "<vis3_shift_insn><vbits>_vis"
- [(set (match_operand:V64N8 0 "register_operand" "=<vconstr>")
- (vis3_shift:V64N8 (match_operand:V64N8 1 "register_operand" "<vconstr>")
- (match_operand:V64N8 2 "register_operand" "<vconstr>")))]
+(define_insn "v<vis3_shift_patname><mode>3"
+ [(set (match_operand:GCM 0 "register_operand" "=<vconstr>")
+ (vis3_shift:GCM (match_operand:GCM 1 "register_operand" "<vconstr>")
+ (match_operand:GCM 2 "register_operand" "<vconstr>")))]
"TARGET_VIS3"
"<vis3_shift_insn><vbits>\t%1, %2, %0")
@@ -8349,26 +8512,21 @@
"TARGET_VIS3"
"fmean16\t%1, %2, %0")
-(define_insn "fpadd64_vis"
- [(set (match_operand:DI 0 "register_operand" "=e")
- (plus:DI (match_operand:DI 1 "register_operand" "e")
- (match_operand:DI 2 "register_operand" "e")))]
- "TARGET_VIS3"
- "fpadd64\t%1, %2, %0")
-
-(define_insn "fpsub64_vis"
- [(set (match_operand:DI 0 "register_operand" "=e")
- (minus:DI (match_operand:DI 1 "register_operand" "e")
- (match_operand:DI 2 "register_operand" "e")))]
+(define_insn "fp<plusminus_insn>64_vis"
+ [(set (match_operand:V1DI 0 "register_operand" "=e")
+ (plusminus:V1DI (match_operand:V1DI 1 "register_operand" "e")
+ (match_operand:V1DI 2 "register_operand" "e")))]
"TARGET_VIS3"
- "fpsub64\t%1, %2, %0")
+ "fp<plusminus_insn>64\t%1, %2, %0")
-(define_mode_iterator VASS [V4HI V2SI V2HI SI])
+(define_mode_iterator VASS [V4HI V2SI V2HI V1SI])
(define_code_iterator vis3_addsub_ss [ss_plus ss_minus])
(define_code_attr vis3_addsub_ss_insn
[(ss_plus "fpadds") (ss_minus "fpsubs")])
+(define_code_attr vis3_addsub_ss_patname
+ [(ss_plus "ssadd") (ss_minus "sssub")])
-(define_insn "<vis3_addsub_ss_insn><vbits>_vis"
+(define_insn "<vis3_addsub_ss_patname><mode>3"
[(set (match_operand:VASS 0 "register_operand" "=<vconstr>")
(vis3_addsub_ss:VASS (match_operand:VASS 1 "register_operand" "<vconstr>")
(match_operand:VASS 2 "register_operand" "<vconstr>")))]
@@ -8383,4 +8541,247 @@
"TARGET_VIS3"
"fucmp<code>8\t%1, %2, %0")
+(define_insn "*naddsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (plus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f"))))]
+ "TARGET_VIS3"
+ "fnadds\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "*nadddf3"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (neg:DF (plus:DF (match_operand:DF 1 "register_operand" "e")
+ (match_operand:DF 2 "register_operand" "e"))))]
+ "TARGET_VIS3"
+ "fnaddd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_insn "*nmulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "f"))
+ (match_operand:SF 2 "register_operand" "f")))]
+ "TARGET_VIS3"
+ "fnmuls\t%1, %2, %0"
+ [(set_attr "type" "fpmul")])
+
+(define_insn "*nmuldf3"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "e"))
+ (match_operand:DF 2 "register_operand" "e")))]
+ "TARGET_VIS3"
+ "fnmuld\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "*nmuldf3_extend"
+ [(set (match_operand:DF 0 "register_operand" "=e")
+ (mult:DF (neg:DF (float_extend:DF
+ (match_operand:SF 1 "register_operand" "f")))
+ (float_extend:DF
+ (match_operand:SF 2 "register_operand" "f"))))]
+ "TARGET_VIS3"
+ "fnsmuld\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fhaddsf_vis"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")]
+ UNSPEC_FHADD))]
+ "TARGET_VIS3"
+ "fhadds\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "fhadddf_vis"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")]
+ UNSPEC_FHADD))]
+ "TARGET_VIS3"
+ "fhaddd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_insn "fhsubsf_vis"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")]
+ UNSPEC_FHSUB))]
+ "TARGET_VIS3"
+ "fhsubs\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "fhsubdf_vis"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")]
+ UNSPEC_FHSUB))]
+ "TARGET_VIS3"
+ "fhsubd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_insn "fnhaddsf_vis"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (unspec:SF [(match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")]
+ UNSPEC_FHADD)))]
+ "TARGET_VIS3"
+ "fnhadds\t%1, %2, %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "fnhadddf_vis"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (unspec:DF [(match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")]
+ UNSPEC_FHADD)))]
+ "TARGET_VIS3"
+ "fnhaddd\t%1, %2, %0"
+ [(set_attr "type" "fp")
+ (set_attr "fptype" "double")])
+
+(define_expand "umulxhi_vis"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "arith_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "")))
+ (const_int 64))))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_umulxhi_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "*umulxhi_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI")))
+ (const_int 64))))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "umulxhi\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
+(define_insn "umulxhi_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r,h")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r,0"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI,rI")))
+ (const_int 64))))
+ (clobber (match_scratch:SI 3 "=&h,X"))
+ (clobber (match_scratch:SI 4 "=&h,X"))]
+ "TARGET_VIS3 && ! TARGET_ARCH64"
+ "* return output_v8plus_mult (insn, operands, \"umulxhi\");"
+ [(set_attr "type" "imul")
+ (set_attr "length" "9,8")])
+
+(define_expand "xmulx_vis"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (truncate:DI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" ""))]
+ UNSPEC_XMUL)))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_xmulx_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "*xmulx_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (truncate:DI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI"))]
+ UNSPEC_XMUL)))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "xmulx\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
+(define_insn "xmulx_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r,h")
+ (truncate:DI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r,0"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI,rI"))]
+ UNSPEC_XMUL)))
+ (clobber (match_scratch:SI 3 "=&h,X"))
+ (clobber (match_scratch:SI 4 "=&h,X"))]
+ "TARGET_VIS3 && ! TARGET_ARCH64"
+ "* return output_v8plus_mult (insn, operands, \"xmulx\");"
+ [(set_attr "type" "imul")
+ (set_attr "length" "9,8")])
+
+(define_expand "xmulxhi_vis"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (truncate:DI
+ (lshiftrt:TI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" ""))]
+ UNSPEC_XMUL)
+ (const_int 64))))]
+ "TARGET_VIS3"
+{
+ if (! TARGET_ARCH64)
+ {
+ emit_insn (gen_xmulxhi_v8plus (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "*xmulxhi_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (truncate:DI
+ (lshiftrt:TI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI"))]
+ UNSPEC_XMUL)
+ (const_int 64))))]
+ "TARGET_VIS3 && TARGET_ARCH64"
+ "xmulxhi\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
+(define_insn "xmulxhi_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=r,h")
+ (truncate:DI
+ (lshiftrt:TI
+ (unspec:TI [(zero_extend:TI
+ (match_operand:DI 1 "arith_operand" "%r,0"))
+ (zero_extend:TI
+ (match_operand:DI 2 "arith_operand" "rI,rI"))]
+ UNSPEC_XMUL)
+ (const_int 64))))
+ (clobber (match_scratch:SI 3 "=&h,X"))
+ (clobber (match_scratch:SI 4 "=&h,X"))]
+ "TARGET_VIS3 && !TARGET_ARCH64"
+ "* return output_v8plus_mult (insn, operands, \"xmulxhi\");"
+ [(set_attr "type" "imul")
+ (set_attr "length" "9,8")])
+
(include "sync.md")
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 613ae731c8e..5ee6396d5fc 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -21,6 +21,10 @@
HeaderInclude
config/sparc/sparc-opts.h
+;; Debug flags
+TargetVariable
+unsigned int sparc_debug
+
mfpu
Target Report Mask(FPU)
Use hardware FP
@@ -73,6 +77,10 @@ mfmaf
Target Report Mask(FMAF)
Use UltraSPARC Fused Multiply-Add extensions
+mpopc
+Target Report Mask(POPC)
+Use UltraSPARC Population-Count instruction
+
mptr64
Target Report RejectNegative Mask(PTR64)
Pointers are 64-bit
@@ -176,10 +184,19 @@ mcmodel=
Target RejectNegative Joined Var(sparc_cmodel_string)
Use given SPARC-V9 code model
+mdebug=
+Target RejectNegative Joined Var(sparc_debug_string)
+Enable debug output
+
mstd-struct-return
Target Report RejectNegative Var(sparc_std_struct_return)
Enable strict 32-bit psABI struct return checking.
+mfix-at697f
+Target Report RejectNegative Var(sparc_fix_at697f)
+Enable workaround for single erratum of AT697F processor
+(corresponding to erratum #13 of AT697E processor)
+
Mask(LITTLE_ENDIAN)
;; Generate code for little-endian
diff --git a/gcc/config/sparc/visintrin.h b/gcc/config/sparc/visintrin.h
index 32e44e55810..deb68b4a724 100644
--- a/gcc/config/sparc/visintrin.h
+++ b/gcc/config/sparc/visintrin.h
@@ -627,4 +627,67 @@ __vis_fucmpeq8 (__v8qi __A, __v8qi __B)
return __builtin_vis_fucmpeq8 (__A, __B);
}
+extern __inline float
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fhadds (float __A, float __B)
+{
+ return __builtin_vis_fhadds (__A, __B);
+}
+
+extern __inline double
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fhaddd (double __A, double __B)
+{
+ return __builtin_vis_fhaddd (__A, __B);
+}
+
+extern __inline float
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fhsubs (float __A, float __B)
+{
+ return __builtin_vis_fhsubs (__A, __B);
+}
+
+extern __inline double
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fhsubd (double __A, double __B)
+{
+ return __builtin_vis_fhsubd (__A, __B);
+}
+
+extern __inline float
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fnhadds (float __A, float __B)
+{
+ return __builtin_vis_fnhadds (__A, __B);
+}
+
+extern __inline double
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_fnhaddd (double __A, double __B)
+{
+ return __builtin_vis_fnhaddd (__A, __B);
+}
+
+extern __inline __i64
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_umulxhi (__i64 __A, __i64 __B)
+{
+ return __builtin_vis_umulxhi (__A, __B);
+}
+
+extern __inline __i64
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_xmulx (__i64 __A, __i64 __B)
+{
+ return __builtin_vis_xmulx (__A, __B);
+}
+
+extern __inline __i64
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__vis_xmulxhi (__i64 __A, __i64 __B)
+{
+ return __builtin_vis_xmulxhi (__A, __B);
+}
+
#endif /* _VISINTRIN_H_INCLUDED */
diff --git a/gcc/config/spu/spu-elf.h b/gcc/config/spu/spu-elf.h
index 818c391f994..146bcb21052 100644
--- a/gcc/config/spu/spu-elf.h
+++ b/gcc/config/spu/spu-elf.h
@@ -35,10 +35,6 @@
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_2 ""
-/* Use "/include" instead of "/usr/include". */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/include"
-
/* We do not provide any "/usr/local/include" directory on SPU. */
#undef LOCAL_INCLUDE_DIR
@@ -77,4 +73,3 @@
mcache-size=16 :-lgcc_cache16k; \
mcache-size=8 :-lgcc_cache8k; \
:-lgcc_cache64k}"
-
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 952aea50444..734c2beec4c 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -500,10 +500,27 @@ static void spu_setup_incoming_varargs (cumulative_args_t cum,
struct gcc_target targetm = TARGET_INITIALIZER;
+/* Define the structure for the machine field in struct function. */
+struct GTY(()) machine_function
+{
+ /* Register to use for PIC accesses. */
+ rtx pic_reg;
+};
+
+/* How to allocate a 'struct machine_function'. */
+static struct machine_function *
+spu_init_machine_status (void)
+{
+ return ggc_alloc_cleared_machine_function ();
+}
+
/* Implement TARGET_OPTION_OVERRIDE. */
static void
spu_option_override (void)
{
+ /* Set up function hooks. */
+ init_machine_status = spu_init_machine_status;
+
/* Small loops will be unpeeled at -O3. For SPU it is more important
to keep code small by default. */
if (!flag_unroll_loops && !flag_peel_loops)
@@ -1741,12 +1758,22 @@ print_operand (FILE * file, rtx x, int code)
static rtx
get_pic_reg (void)
{
- rtx pic_reg = pic_offset_table_rtx;
if (!reload_completed && !reload_in_progress)
abort ();
- if (current_function_is_leaf && !df_regs_ever_live_p (LAST_ARG_REGNUM))
- pic_reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
- return pic_reg;
+
+ /* If we've already made the decision, we need to keep with it. Once we've
+ decided to use LAST_ARG_REGNUM, future calls to df_regs_ever_live_p may
+ return true since the register is now live; this should not cause us to
+ "switch back" to using pic_offset_table_rtx. */
+ if (!cfun->machine->pic_reg)
+ {
+ if (current_function_is_leaf && !df_regs_ever_live_p (LAST_ARG_REGNUM))
+ cfun->machine->pic_reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
+ else
+ cfun->machine->pic_reg = pic_offset_table_rtx;
+ }
+
+ return cfun->machine->pic_reg;
}
/* Split constant addresses to handle cases that are too large.
@@ -1849,7 +1876,6 @@ spu_split_immediate (rtx * ops)
{
rtx pic_reg = get_pic_reg ();
emit_insn (gen_addsi3 (ops[0], ops[0], pic_reg));
- crtl->uses_pic_offset_table = 1;
}
return flag_pic || c == IC_IL2s;
}
@@ -1875,9 +1901,7 @@ need_to_save_reg (int regno, int saving)
return 1;
if (flag_pic
&& regno == PIC_OFFSET_TABLE_REGNUM
- && (!saving || crtl->uses_pic_offset_table)
- && (!saving
- || !current_function_is_leaf || df_regs_ever_live_p (LAST_ARG_REGNUM)))
+ && (!saving || cfun->machine->pic_reg == pic_offset_table_rtx))
return 1;
return 0;
}
@@ -1991,8 +2015,8 @@ spu_expand_prologue (void)
rtx scratch_reg_0, scratch_reg_1;
rtx insn, real;
- if (flag_pic && optimize == 0)
- crtl->uses_pic_offset_table = 1;
+ if (flag_pic && optimize == 0 && !cfun->machine->pic_reg)
+ cfun->machine->pic_reg = pic_offset_table_rtx;
if (spu_naked_function_p (current_function_decl))
return;
@@ -2029,9 +2053,9 @@ spu_expand_prologue (void)
}
}
- if (flag_pic && crtl->uses_pic_offset_table)
+ if (flag_pic && cfun->machine->pic_reg)
{
- rtx pic_reg = get_pic_reg ();
+ rtx pic_reg = cfun->machine->pic_reg;
insn = emit_insn (gen_load_pic_offset (pic_reg, scratch_reg_0));
insn = emit_insn (gen_subsi3 (pic_reg, pic_reg, scratch_reg_0));
}
@@ -6391,13 +6415,24 @@ spu_emit_vector_compare (enum rtx_code rcode,
try_again = true;
break;
case NE:
+ case UNEQ:
+ case UNLE:
+ case UNLT:
+ case UNGE:
+ case UNGT:
+ case UNORDERED:
/* Treat A != B as ~(A==B). */
{
+ enum rtx_code rev_code;
enum insn_code nor_code;
- rtx eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode);
+ rtx rev_mask;
+
+ rev_code = reverse_condition_maybe_unordered (rcode);
+ rev_mask = spu_emit_vector_compare (rev_code, op0, op1, dest_mode);
+
nor_code = optab_handler (one_cmpl_optab, dest_mode);
gcc_assert (nor_code != CODE_FOR_nothing);
- emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
+ emit_insn (GEN_FCN (nor_code) (mask, rev_mask));
if (dmode != dest_mode)
{
rtx temp = gen_reg_rtx (dest_mode);
@@ -6442,6 +6477,48 @@ spu_emit_vector_compare (enum rtx_code rcode,
return mask;
}
break;
+ case LTGT:
+ /* Try LT OR GT */
+ {
+ rtx lt_rtx, gt_rtx;
+ enum insn_code ior_code;
+
+ lt_rtx = spu_emit_vector_compare (LT, op0, op1, dest_mode);
+ gt_rtx = spu_emit_vector_compare (GT, op0, op1, dest_mode);
+
+ ior_code = optab_handler (ior_optab, dest_mode);
+ gcc_assert (ior_code != CODE_FOR_nothing);
+ emit_insn (GEN_FCN (ior_code) (mask, lt_rtx, gt_rtx));
+ if (dmode != dest_mode)
+ {
+ rtx temp = gen_reg_rtx (dest_mode);
+ convert_move (temp, mask, 0);
+ return temp;
+ }
+ return mask;
+ }
+ break;
+ case ORDERED:
+ /* Implement as (A==A) & (B==B) */
+ {
+ rtx a_rtx, b_rtx;
+ enum insn_code and_code;
+
+ a_rtx = spu_emit_vector_compare (EQ, op0, op0, dest_mode);
+ b_rtx = spu_emit_vector_compare (EQ, op1, op1, dest_mode);
+
+ and_code = optab_handler (and_optab, dest_mode);
+ gcc_assert (and_code != CODE_FOR_nothing);
+ emit_insn (GEN_FCN (and_code) (mask, a_rtx, b_rtx));
+ if (dmode != dest_mode)
+ {
+ rtx temp = gen_reg_rtx (dest_mode);
+ convert_move (temp, mask, 0);
+ return temp;
+ }
+ return mask;
+ }
+ break;
default:
gcc_unreachable ();
}
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index 676d54e8de0..00cfaa4be55 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -4395,6 +4395,18 @@ selb\t%0,%4,%0,%3"
"shufb\t%0,%1,%2,%3"
[(set_attr "type" "shuf")])
+(define_expand "vec_permv16qi"
+ [(set (match_operand:V16QI 0 "spu_reg_operand" "")
+ (unspec:V16QI
+ [(match_operand:V16QI 1 "spu_reg_operand" "")
+ (match_operand:V16QI 2 "spu_reg_operand" "")
+ (match_operand:V16QI 3 "spu_reg_operand" "")]
+ UNSPEC_SHUFB))]
+ ""
+ {
+ operands[3] = gen_lowpart (TImode, operands[3]);
+ })
+
(define_insn "nop"
[(unspec_volatile [(const_int 0)] UNSPECV_NOP)]
""
diff --git a/gcc/config/spu/t-spu-elf b/gcc/config/spu/t-spu-elf
index 3f9510112f7..b48106efed2 100644
--- a/gcc/config/spu/t-spu-elf
+++ b/gcc/config/spu/t-spu-elf
@@ -15,10 +15,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Define system directory to match STANDARD_INCLUDE_DIR in spu-elf.h,
-# allowing combined SPU/PPU sysroot builds.
-NATIVE_SYSTEM_HEADER_DIR = /include
-
# Suppress building libgcc1.a
LIBGCC1 =
CROSS_LIBGCC1 =
diff --git a/gcc/config/t-gnu b/gcc/config/t-gnu
deleted file mode 100644
index 7be5d00a718..00000000000
--- a/gcc/config/t-gnu
+++ /dev/null
@@ -1,2 +0,0 @@
-# In GNU, "/usr" is a four-letter word.
-NATIVE_SYSTEM_HEADER_DIR = /include
diff --git a/gcc/config/vms/vms.c b/gcc/config/vms/vms.c
index 62a16619856..44940a3aa3b 100644
--- a/gcc/config/vms/vms.c
+++ b/gcc/config/vms/vms.c
@@ -99,8 +99,11 @@ vms_patch_builtins (void)
unsigned int i;
/* Fwrite on VMS is non-standard. */
- implicit_built_in_decls[(int) BUILT_IN_FWRITE] = NULL_TREE;
- implicit_built_in_decls[(int) BUILT_IN_FWRITE_UNLOCKED] = NULL_TREE;
+ if (builtin_decl_implicit_p (BUILT_IN_WRITE))
+ set_builtin_decl_implicit_p (BUILT_IN_WRITE, false);
+
+ if (builtin_decl_implicit_p (BUILT_IN_WRITE_UNLOCKED))
+ set_builtin_decl_implicit_p (BUILT_IN_WRITE_UNLOCKED, false);
/* Define aliases for names. */
for (i = 0; i < NBR_CRTL_NAMES; i++)
diff --git a/gcc/config/vms/xm-vms.h b/gcc/config/vms/xm-vms.h
index 7907f9263cf..816935b5062 100644
--- a/gcc/config/vms/xm-vms.h
+++ b/gcc/config/vms/xm-vms.h
@@ -1,6 +1,6 @@
/* Configuration for GCC for hosting on VMS
using a Unix style C library.
- Copyright (C) 1996, 1997, 2001, 2004, 2007, 2009
+ Copyright (C) 1996, 1997, 2001, 2004, 2007, 2009, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -55,4 +55,3 @@ do \
#define STANDARD_EXEC_PREFIX "/gnu/libexec/gcc/"
#define STANDARD_STARTFILE_PREFIX "/gnu/lib/"
-#define STANDARD_INCLUDE_DIR "/gnu/include"
diff --git a/gcc/configure b/gcc/configure
index dbae03e7e8a..b4bd02605e4 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -729,6 +729,7 @@ USE_NLS
extra_opt_files
extra_modes_file
gthread_flags
+NATIVE_SYSTEM_HEADER_DIR
objext
manext
LIBICONV_DEP
@@ -766,7 +767,6 @@ TARGET_SYSTEM_ROOT_DEFINE
TARGET_SYSTEM_ROOT
RUNTIME_ROOT_PREFIX_DEFINE
SYSROOT_CFLAGS_FOR_TARGET
-NATIVE_SYSTEM_HEADER_DIR
enable_shared
enable_fixed_point
enable_decimal_float
@@ -7167,26 +7167,21 @@ fi
-# The use of native_system_header_dir here is for the value (optionally)
-# configured here. Uses of NATIVE_SYSTEM_HEADER_DIR in this file refer
-# to the make variable defined in Makefile or in target make fragments.
# Check whether --with-native-system-header-dir was given.
if test "${with_native_system_header_dir+set}" = set; then :
withval=$with_native_system_header_dir;
case ${with_native_system_header_dir} in
- yes|no) as_fn_error "bad value ${withval} given for native system include directory" "$LINENO" 5 ;;
- /*) ;;
- *) as_fn_error "${withval} should be an absolute directory" "$LINENO" 5 ;;
+ yes|no) as_fn_error "bad value ${withval} given for --with-native-system-header-dir" "$LINENO" 5 ;;
+ /* | [A-Za-z]:[\\/]*) ;;
+ *) as_fn_error "--with-native-system-header-dir argument ${withval} must be an absolute directory" "$LINENO" 5 ;;
esac
- native_system_header_dir="${withval}"
+ configured_native_system_header_dir="${withval}"
else
- native_system_header_dir=/usr/include
+ configured_native_system_header_dir=
fi
-NATIVE_SYSTEM_HEADER_DIR=$native_system_header_dir
-
# Check whether --with-build-sysroot was given.
@@ -9067,7 +9062,7 @@ fi
for ac_func in times clock kill getrlimit setrlimit atoll atoq \
sysconf strsignal getrusage nl_langinfo \
gettimeofday mbstowcs wcswidth mmap setlocale \
- clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked
+ clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked madvise
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -10460,6 +10455,8 @@ $as_echo "#define HAVE_LANGINFO_CODESET 1" >>confdefs.h
# We will need to find libiberty.h and ansidecl.h
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
+saved_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include"
for ac_func in getenv atol asprintf sbrk abort atof getcwd getwd \
strsignal strstr strverscmp \
errno snprintf vsnprintf vasprintf malloc realloc calloc \
@@ -10764,6 +10761,127 @@ fi
done
+# g++ on Solaris 10+ defines _XOPEN_SOURCE=600, which hides the madvise()
+# prototype.
+if test "$ENABLE_BUILD_WITH_CXX" = "yes"; then :
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ for ac_func in madvise
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if { as_var=gcc_cv_have_decl_$ac_func; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+ #include "ansidecl.h"
+ #include "system.h"
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+else
+ for ac_func in madvise
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if { as_var=gcc_cv_have_decl_$ac_func; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+ #include "ansidecl.h"
+ #include "system.h"
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+fi
+
# More time-related stuff.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct tms" >&5
$as_echo_n "checking for struct tms... " >&6; }
@@ -10840,8 +10958,9 @@ $as_echo "#define HAVE_CLOCK_T 1" >>confdefs.h
fi
-# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
+# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
+CXXFLAGS="$saved_CXXFLAGS"
# Check whether --enable-initfini-array was given.
if test "${enable_initfini_array+set}" = set; then :
@@ -11211,6 +11330,12 @@ if test "$host_xm_file" != "$build_xm_file"; then
fi
fi
+if test -n "$configured_native_system_header_dir"; then
+ native_system_header_dir=$configured_native_system_header_dir
+fi
+NATIVE_SYSTEM_HEADER_DIR="$native_system_header_dir"
+
+
case ${host} in
powerpc*-*-darwin*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mcontext_t fields have underscores" >&5
@@ -18002,7 +18127,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18005 "configure"
+#line 18130 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18108,7 +18233,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18111 "configure"
+#line 18236 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -23649,6 +23774,14 @@ elif test x$gcc_cv_ld != x; then
gcc_cv_ld_static_option="-noso"
gcc_cv_ld_dynamic_option="-so_archive"
;;
+ # HP-UX ld uses -a flags to select between shared and archive.
+ *-*-hpux*)
+ if test x"$gnu_ld" = xno; then
+ gcc_cv_ld_static_dynamic=yes
+ gcc_cv_ld_static_option="-aarchive_shared"
+ gcc_cv_ld_dynamic_option="-adefault"
+ fi
+ ;;
# IRIX 6 ld supports -Bstatic/-Bdynamic.
mips-sgi-irix6*)
gcc_cv_ld_static_dynamic=yes
@@ -24133,6 +24266,8 @@ else
gcc_cv_as_sparc_fmaf=no
if test x$gcc_cv_as != x; then
$as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
.align 4
fmaddd %f0, %f2, %f4, %f6
addxccc %g1, %g2, %g3
@@ -26554,6 +26689,7 @@ fi
$as_echo_n "checking sys/sdt.h in the target C library... " >&6; }
have_sys_sdt_h=no
if test -f $target_header_dir/sys/sdt.h; then
+ have_sys_sdt_h=yes
$as_echo "#define HAVE_SYS_SDT_H 1" >>confdefs.h
diff --git a/gcc/configure.ac b/gcc/configure.ac
index acc8427b06e..9741fc669a3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -725,22 +725,18 @@ AC_ARG_ENABLE(shared,
], [enable_shared=yes])
AC_SUBST(enable_shared)
-# The use of native_system_header_dir here is for the value (optionally)
-# configured here. Uses of NATIVE_SYSTEM_HEADER_DIR in this file refer
-# to the make variable defined in Makefile or in target make fragments.
AC_ARG_WITH([native-system-header-dir],
[ --with-native-system-header-dir=dir
use dir as the directory to look for standard
system header files in. Defaults to /usr/include.],
[
case ${with_native_system_header_dir} in
- yes|no) AC_MSG_ERROR([bad value ${withval} given for native system include directory]) ;;
- /*) ;;
- *) AC_MSG_ERROR([${withval} should be an absolute directory]) ;;
+ yes|no) AC_MSG_ERROR([bad value ${withval} given for --with-native-system-header-dir]) ;;
+ /* | [[A-Za-z]]:[[\\/]]*) ;;
+ *) AC_MSG_ERROR([--with-native-system-header-dir argument ${withval} must be an absolute directory]) ;;
esac
- native_system_header_dir="${withval}"
-], [native_system_header_dir=/usr/include])
-AC_SUBST(NATIVE_SYSTEM_HEADER_DIR, $native_system_header_dir)
+ configured_native_system_header_dir="${withval}"
+], [configured_native_system_header_dir=])
AC_ARG_WITH(build-sysroot,
[AS_HELP_STRING([--with-build-sysroot=sysroot],
@@ -1068,7 +1064,7 @@ define(gcc_UNLOCKED_FUNCS, clearerr_unlocked feof_unlocked dnl
AC_CHECK_FUNCS(times clock kill getrlimit setrlimit atoll atoq \
sysconf strsignal getrusage nl_langinfo \
gettimeofday mbstowcs wcswidth mmap setlocale \
- gcc_UNLOCKED_FUNCS)
+ gcc_UNLOCKED_FUNCS madvise)
if test x$ac_cv_func_mbstowcs = xyes; then
AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
@@ -1122,6 +1118,8 @@ AM_LANGINFO_CODESET
# We will need to find libiberty.h and ansidecl.h
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
+saved_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include"
gcc_AC_CHECK_DECLS(getenv atol asprintf sbrk abort atof getcwd getwd \
strsignal strstr strverscmp \
errno snprintf vsnprintf vasprintf malloc realloc calloc \
@@ -1174,6 +1172,21 @@ gcc_AC_CHECK_DECLS(sigaltstack, , ,[
#include <signal.h>
])
+# g++ on Solaris 10+ defines _XOPEN_SOURCE=600, which hides the madvise()
+# prototype.
+AS_IF([test "$ENABLE_BUILD_WITH_CXX" = "yes"],
+ [AC_LANG_PUSH([C++])
+ gcc_AC_CHECK_DECLS(madvise, , ,[
+ #include "ansidecl.h"
+ #include "system.h"
+ ])
+ AC_LANG_POP([C++])],
+ [gcc_AC_CHECK_DECLS(madvise, , ,[
+ #include "ansidecl.h"
+ #include "system.h"
+ ])
+])
+
# More time-related stuff.
AC_CACHE_CHECK(for struct tms, ac_cv_struct_tms, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@@ -1200,8 +1213,9 @@ if test $gcc_cv_type_clock_t = yes; then
[Define if <time.h> defines clock_t.])
fi
-# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
+# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
+CXXFLAGS="$saved_CXXFLAGS"
gcc_AC_INITFINI_ARRAY
@@ -1372,6 +1386,12 @@ if test "$host_xm_file" != "$build_xm_file"; then
fi
fi
+if test -n "$configured_native_system_header_dir"; then
+ native_system_header_dir=$configured_native_system_header_dir
+fi
+NATIVE_SYSTEM_HEADER_DIR="$native_system_header_dir"
+AC_SUBST(NATIVE_SYSTEM_HEADER_DIR)
+
case ${host} in
powerpc*-*-darwin*)
AC_CACHE_CHECK([whether mcontext_t fields have underscores],
@@ -3289,6 +3309,14 @@ elif test x$gcc_cv_ld != x; then
gcc_cv_ld_static_option="-noso"
gcc_cv_ld_dynamic_option="-so_archive"
;;
+ # HP-UX ld uses -a flags to select between shared and archive.
+ *-*-hpux*)
+ if test x"$gnu_ld" = xno; then
+ gcc_cv_ld_static_dynamic=yes
+ gcc_cv_ld_static_option="-aarchive_shared"
+ gcc_cv_ld_dynamic_option="-adefault"
+ fi
+ ;;
# IRIX 6 ld supports -Bstatic/-Bdynamic.
mips-sgi-irix6*)
gcc_cv_ld_static_dynamic=yes
@@ -3524,6 +3552,8 @@ foo:
gcc_cv_as_sparc_fmaf,,
[-xarch=v9d],
[.text
+ .register %g2, #scratch
+ .register %g3, #scratch
.align 4
fmaddd %f0, %f2, %f4, %f6
addxccc %g1, %g2, %g3
@@ -4609,6 +4639,7 @@ GCC_TARGET_TEMPLATE([HAVE_SYS_SDT_H])
AC_MSG_CHECKING(sys/sdt.h in the target C library)
have_sys_sdt_h=no
if test -f $target_header_dir/sys/sdt.h; then
+ have_sys_sdt_h=yes
AC_DEFINE(HAVE_SYS_SDT_H, 1,
[Define if your target C library provides sys/sdt.h])
fi
diff --git a/gcc/convert.c b/gcc/convert.c
index a647193ca94..f04b2048194 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -745,6 +745,15 @@ convert_to_integer (tree type, tree expr)
tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);
tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);
+ /* Do not try to narrow operands of pointer subtraction;
+ that will interfere with other folding. */
+ if (ex_form == MINUS_EXPR
+ && CONVERT_EXPR_P (arg0)
+ && CONVERT_EXPR_P (arg1)
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0))))
+ break;
+
if (outprec >= BITS_PER_WORD
|| TRULY_NOOP_TRUNCATION (outprec, inprec)
|| inprec > TYPE_PRECISION (TREE_TYPE (arg0))
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e9173050249..a32a7b9fca0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,288 @@
+2011-10-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/13657
+ * class.c (instantiate_type): Fix error message.
+
+2011-10-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/50793
+ * tree.c (bot_manip): Propagate AGGR_INIT_ZERO_FIRST.
+
+2011-10-19 Roland Stigge <stigge@antcom.de>
+
+ PR translation/49704
+ * semantics.c (potential_constant_expression_1): Use "AST" instead of
+ "ast" in sorry message.
+
+2011-10-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38761
+ PR c++/40872
+ * decl.c (duplicate_decls, make_typename_type, grokdeclarator): Use
+ G_() in error message strings to facilitate translation.
+ * semantics.c (finish_id_expression): Likewise.
+ * parser.c (cp_parser_nested_name_specifier_opt,
+ cp_parser_parameter_declaration): Likewise.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50531
+ * pt.c (instantiate_decl): Recognize when a function defaulted
+ outside the class is already instantiated.
+
+ PR c++/50742
+ * decl.c (check_previous_goto_1): Handle using-decl.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50500
+ DR 1082
+ * class.c (type_has_user_declared_move_constructor): New.
+ (type_has_user_declared_move_assign): New.
+ (add_implicitly_declared_members): Add lazy copy ops
+ even if there's a move.
+ * method.c (lazily_declare_fn): Delete implicit copies
+ if there's a move.
+ (maybe_explain_implicit_delete): Explain this. Use inform rather
+ than error.
+ * cp-tree.h: Declare new fns.
+
+2011-10-18 Diego Novillo <dnovillo@google.com>
+
+ * parser.c: Remove ENABLE_CHECKING markers around debugging
+ routines.
+ (cp_lexer_dump_tokens): Add arguments START_TOKEN and CURR_TOKEN.
+ Make static
+ When printing CURR_TOKEN surround it in [[ ]].
+ Start printing at START_TOKEN.
+ Update all users.
+ (cp_debug_print_tree_if_set): New.
+ (cp_debug_print_context): New.
+ (cp_debug_print_context_stack): New.
+ (cp_debug_print_flag): New.
+ (cp_debug_print_unparsed_function): New.
+ (cp_debug_print_unparsed_queues): New.
+ (cp_debug_parser_tokens): New.
+ (cp_debug_parser): New.
+ (cp_lexer_start_debugging): Set cp_lexer_debug_stream to stderr.
+ (cp_lexer_stop_debugging): Set cp_lexer_debug_stream to NULL.
+ * parser.h (cp_lexer_dump_tokens): Remove declaration.
+ (cp_debug_parser): Declare.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * cp-tree.def: Add BASES as a new tree code.
+ * cp-tree.h (enum cp_trait_kind): Add CPTK_BASES, CPTK_DIRECT_BASES.
+ (BASES_TYPE, BASES_DIRECT): Define.
+ (calculate_bases, finish_bases, calculate_direct_bases): Declare.
+ * parser.c (cp_parser_trait_expr, cp_parser_template_argument_list,
+ (cp_parser_simple_type_specifier, cp_parser_save_nsdmi): Use them.
+ * pt.c (find_parameter_packs_r, tsubst_pack_expansion): Likewise.
+ * semantics.c (calculate_bases, finish_bases, calculate_direct_bases,
+ dfs_calculate_bases_pre, dfs_calculate_bases_post,
+ calculate_bases_helper): Define.
+
+2011-10-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/50736
+ * parser.c (cp_parser_lambda_introducer): Check for more
+ invalid captures.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44524
+ * typeck.c (build_class_member_access_expr): Provide a better error
+ message for X.Y where X is a pointer to class type.
+ (finish_class_member_access_expr): Likewise.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * error.c (cp_diagnostic_starter): Pass the relevant location to
+ diagnostic_report_current_module.
+ (cp_diagnostic_finalizer): Call virt_loc_aware_diagnostic_finalizer.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/48489
+ * typeck.c (finish_class_member_access_expr): Fix error call
+ for TREE_CODE (access_path) == TREE_BINFO.
+
+2011-10-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50732
+ * semantics.c (finish_trait_expr): Do not try to instantiate the
+ the base type of an __is_base_of trait.
+ (check_trait_type): Return a tree; use complete_type_or_else.
+
+2011-10-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/50563
+ * parser.c (cp_parser_cache_group): Handle end==CPP_COMMA.
+ (cp_parser_save_nsdmi): Pass it.
+
+ PR c++/50707
+ * method.c (walk_field_subobs): Check for NSDMI before
+ complaining about uninitialized fields.
+
+ * pt.c (tsubst_decl) [FIELD_DECL]: Use void_zero_node
+ instead of error_mark_node as a placeholder.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38174
+ * call.c (add_builtin_candidate): If two pointers have a composite
+ pointer type, generate a single candidate with that type.
+
+2011-10-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/50614
+ * cp-tree.h (VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK): New.
+ (DECL_TEMPLATE_INFO): Use it.
+ * pt.c (tsubst_decl) [FIELD_DECL]: Set DECL_TEMPLATE_INFO
+ if the decl has an NSDMI.
+ * init.c (perform_member_init): Use it.
+
+ PR c++/50437
+ * cp-tree.h (struct tree_lambda_expr): Add closure field.
+ (LAMBDA_EXPR_CLOSURE): New.
+ * pt.c (tsubst_copy_and_build) [LAMBDA_EXPR]: Likewise.
+ * semantics.c (build_lambda_object): Use it instead of TREE_TYPE.
+ (begin_lambda_type, lambda_function, add_capture): Likewise.
+ (add_default_capture, lambda_expr_this_capture): Likewise.
+
+2011-10-13 Diego Novillo <dnovillo@google.com>
+
+ * cp-tree.h (struct language_function): Rename in_function_try_handler
+ to x_in_function_try_handler.
+ Rename in_base_initializer to x_in_base_initializer.
+ Update all users.
+
+2011-10-13 Diego Novillo <dnovillo@google.com>
+
+ * class.c (sorted_fields_type_new): Factor out of ...
+ (finish_struct_1): ... here.
+
+2011-10-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/50618
+ * init.c (expand_aggr_init_1): Don't zero-initialize virtual
+ bases of a base subobject.
+
+2011-10-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50594
+ * decl.c (cxx_init_decl_processing): Add
+ __attribute__((externally_visible)) to operator new and
+ operator delete library fn.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * decl.c (duplicate_decls): Delete old interface with two parallel
+ arrays to hold standard builtin declarations, and replace it with
+ a function based interface that can support creating builtins on
+ the fly in the future. Change all uses, and poison the old
+ names. Make sure 0 is not a legitimate builtin index.
+ * except.c (build_eh_type_type): Ditto.
+ (choose_personality_routine): Ditto.
+ * semantics.c (finish_omp_atomic): Ditto.
+ (finish_omp_barrier): Ditto.
+ (finish_omp_flush): Ditto.
+ (finish_omp_taskwait): Ditto.
+
+2011-10-11 Jason Merrill <jason@redhat.com>
+
+ PR c++/49855
+ PR c++/49896
+ * cp-tree.def (IMPLICIT_CONV_EXPR): New.
+ * call.c (perform_implicit_conversion_flags): Build it
+ instead of NOP_EXPR.
+ * cp-objcp-common.c (cp_common_init_ts): It's typed.
+ * cxx-pretty-print.c (pp_cxx_cast_expression): Handle it.
+ (pp_cxx_expression): Likewise.
+ * error.c (dump_expr): Likewise.
+ * semantics.c (potential_constant_expression_1): Likewise.
+ * tree.c (cp_tree_equal): Likewise.
+ (cp_walk_subtrees): Likewise.
+ * pt.c (iterative_hash_template_arg): Likewise.
+ (for_each_template_parm_r): Likewise.
+ (type_dependent_expression_p): Likewise.
+ (tsubst_copy, tsubst_copy_and_build): Handle IMPLICIT_CONV_EXPR
+ and CONVERT_EXPR.
+ * cp-tree.h (IMPLICIT_CONV_EXPR_DIRECT_INIT): New.
+
+2011-10-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50611
+ * pt.c (tsubst_copy_and_build): If (complain & tf_error) is false
+ do not call unqualified_name_lookup_error.
+
+2011-10-10 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50660
+ * call.c (conversion_null_warnings): Don't look through references.
+
+2011-10-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38980
+ * init.c (constant_value_1): Add bool parameter.
+ (decl_constant_value_safe): Add.
+ (integral_constant_value): Adjust.
+ (decl_constant_value): Adjust.
+ * cp-tree.h (decl_constant_value_safe): Declare.
+ * typeck.c (decay_conversion): Use decl_constant_value_safe.
+ * call.c (convert_like_real): Likewise.
+
+2011-10-09 Jakub Jelinek <jakub@redhat.com>
+ Diego Novillo <dnovillo@google.com>
+
+ * pt.c (reregister_specialization): Use htab_find instead of
+ htab_find_slot with INSERT.
+ (maybe_process_partial_specialization, lookup_template_class_1): Change
+ slot variable type to void ** to avoid aliasing problems.
+ (register_specialization): Likewise. Use slot != NULL instead of
+ more expensive !optimize_specialization_lookup_p (tmpl) test.
+
+2011-10-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/34927
+ * typeck2.c (abstract_virtuals_error_sfinae): Don't produce duplicate
+ inform messages in case of cloned destructor.
+
+2011-10-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/39164
+ * decl.c (grokfndecl): Diagnose redefinition of defaulted fn.
+
+2011-10-02 Jason Merrill <jason@redhat.com>
+
+ * pt.c (tsubst_pack_expansion): Re-use ARGUMENT_PACK_SELECTs.
+ Change unsubstituted_packs to bool.
+
+ * parser.c (cp_parser_range_for): Don't try to deduce from {}
+ in a template.
+
+ PR c++/35722
+ Implement N2555 (expanding pack expansion to fixed parm list)
+ * pt.c (coerce_template_parms): Allow expanding a pack expansion
+ to a fixed-length argument list.
+ (unify_pack_expansion): Handle explicit args properly.
+ (unify) [TREE_VEC]: Handle pack expansions here.
+ [TYPE_ARGUMENT_PACK]: Not here.
+ (tsubst_pack_expansion): Don't try to do partial substitution.
+ (pack_deducible_p): New.
+ (fn_type_unification): Use it.
+ (find_parameter_packs_r): Take the TYPE_MAIN_VARIANT
+ of a type parameter.
+ (check_non_deducible_conversion): Split from type_unification_real.
+ (unify_one_argument): Split from type_unification_real...
+ (unify_pack_expansion): ...and here. Drop call_args_p parm.
+ (type_unification_real, unify, more_specialized_fn): Adjust.
+
+ * class.c (fixed_type_or_null): Handle NSDMI.
+ * method.c (walk_field_subobs): Disable NSDMI noexcept checking
+ for now.
+
2011-09-30 Jason Merrill <jason@redhat.com>
* cp-tree.h (TREE_NEGATED_INT): Remove.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a52ec29eb66..7e87bdfea02 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2582,6 +2582,21 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
|| MAYBE_CLASS_TYPE_P (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
{
+ if (TYPE_PTR_P (type1) || TYPE_PTR_TO_MEMBER_P (type1))
+ {
+ tree cptype = composite_pointer_type (type1, type2,
+ error_mark_node,
+ error_mark_node,
+ CPO_CONVERSION,
+ tf_none);
+ if (cptype != error_mark_node)
+ {
+ build_builtin_candidate
+ (candidates, fnname, cptype, cptype, args, argtypes, flags);
+ return;
+ }
+ }
+
build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags);
build_builtin_candidate
@@ -5514,10 +5529,9 @@ build_temp (tree expr, tree type, int flags,
static void
conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
{
- tree t = non_reference (totype);
-
/* Issue warnings about peculiar, but valid, uses of NULL. */
- if (expr == null_node && TREE_CODE (t) != BOOLEAN_TYPE && ARITHMETIC_TYPE_P (t))
+ if (expr == null_node && TREE_CODE (totype) != BOOLEAN_TYPE
+ && ARITHMETIC_TYPE_P (totype))
{
if (fn)
warning_at (input_location, OPT_Wconversion_null,
@@ -5525,11 +5539,11 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
argnum, fn);
else
warning_at (input_location, OPT_Wconversion_null,
- "converting to non-pointer type %qT from NULL", t);
+ "converting to non-pointer type %qT from NULL", totype);
}
/* Issue warnings if "false" is converted to a NULL pointer */
- else if (expr == boolean_false_node && POINTER_TYPE_P (t))
+ else if (expr == boolean_false_node && TYPE_PTR_P (totype))
{
if (fn)
warning_at (input_location, OPT_Wconversion_null,
@@ -5537,7 +5551,7 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
"of %qD", argnum, fn);
else
warning_at (input_location, OPT_Wconversion_null,
- "converting %<false%> to pointer type %qT", t);
+ "converting %<false%> to pointer type %qT", totype);
}
}
@@ -5703,7 +5717,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
leave it as an lvalue. */
if (inner >= 0)
{
- expr = decl_constant_value (expr);
+ expr = decl_constant_value_safe (expr);
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
@@ -8398,13 +8412,19 @@ perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain
}
expr = error_mark_node;
}
- else if (processing_template_decl)
+ else if (processing_template_decl
+ /* As a kludge, we always perform conversions between scalar
+ types, as IMPLICIT_CONV_EXPR confuses c_finish_omp_for. */
+ && !(SCALAR_TYPE_P (type) && SCALAR_TYPE_P (TREE_TYPE (expr))))
{
/* In a template, we are only concerned about determining the
type of non-dependent expressions, so we do not have to
- perform the actual conversion. */
- if (TREE_TYPE (expr) != type)
- expr = build_nop (type, expr);
+ perform the actual conversion. But for initializers, we
+ need to be able to perform it at instantiation
+ (or fold_non_dependent_expr) time. */
+ expr = build1 (IMPLICIT_CONV_EXPR, type, expr);
+ if (!(flags & LOOKUP_ONLYCONVERTING))
+ IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true;
}
else
expr = convert_like (conv, expr, complain);
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a7d8218055f..ee6ca049d3f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2736,13 +2736,12 @@ add_implicitly_declared_members (tree t,
If a class definition does not explicitly declare a copy
constructor, one is declared implicitly. */
- if (! TYPE_HAS_COPY_CTOR (t) && ! TYPE_FOR_JAVA (t)
- && !type_has_move_constructor (t))
+ if (! TYPE_HAS_COPY_CTOR (t) && ! TYPE_FOR_JAVA (t))
{
TYPE_HAS_COPY_CTOR (t) = 1;
TYPE_HAS_CONST_COPY_CTOR (t) = !cant_have_const_cctor;
CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
- if (cxx_dialect >= cxx0x)
+ if (cxx_dialect >= cxx0x && !type_has_move_constructor (t))
CLASSTYPE_LAZY_MOVE_CTOR (t) = 1;
}
@@ -2750,13 +2749,12 @@ add_implicitly_declared_members (tree t,
when it is needed. For now, just record whether or not the type
of the parameter to the assignment operator will be a const or
non-const reference. */
- if (!TYPE_HAS_COPY_ASSIGN (t) && !TYPE_FOR_JAVA (t)
- && !type_has_move_assign (t))
+ if (!TYPE_HAS_COPY_ASSIGN (t) && !TYPE_FOR_JAVA (t))
{
TYPE_HAS_COPY_ASSIGN (t) = 1;
TYPE_HAS_CONST_COPY_ASSIGN (t) = !cant_have_const_assignment;
CLASSTYPE_LAZY_COPY_ASSIGN (t) = 1;
- if (cxx_dialect >= cxx0x)
+ if (cxx_dialect >= cxx0x && !type_has_move_assign (t))
CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1;
}
@@ -4495,6 +4493,54 @@ type_has_move_assign (tree t)
return false;
}
+/* Returns true iff class T has a move constructor that was explicitly
+ declared in the class body. Note that this is different from
+ "user-provided", which doesn't include functions that are defaulted in
+ the class. */
+
+bool
+type_has_user_declared_move_constructor (tree t)
+{
+ tree fns;
+
+ if (CLASSTYPE_LAZY_MOVE_CTOR (t))
+ return false;
+
+ if (!CLASSTYPE_METHOD_VEC (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (move_fn_p (fn) && !DECL_ARTIFICIAL (fn))
+ return true;
+ }
+
+ return false;
+}
+
+/* Returns true iff class T has a move assignment operator that was
+ explicitly declared in the class body. */
+
+bool
+type_has_user_declared_move_assign (tree t)
+{
+ tree fns;
+
+ if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
+ return false;
+
+ for (fns = lookup_fnfields_slot (t, ansi_assopname (NOP_EXPR));
+ fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (move_fn_p (fn) && !DECL_ARTIFICIAL (fn))
+ return true;
+ }
+
+ return false;
+}
+
/* Nonzero if we need to build up a constructor call when initializing an
object of this class, either because it has a user-provided constructor
or because it doesn't have a default constructor (so we need to give an
@@ -5663,6 +5709,22 @@ determine_key_method (tree type)
return;
}
+
+/* Allocate and return an instance of struct sorted_fields_type with
+ N fields. */
+
+static struct sorted_fields_type *
+sorted_fields_type_new (int n)
+{
+ struct sorted_fields_type *sft;
+ sft = ggc_alloc_sorted_fields_type (sizeof (struct sorted_fields_type)
+ + n * sizeof (tree));
+ sft->len = n;
+
+ return sft;
+}
+
+
/* Perform processing required when the definition of T (a class type)
is complete. */
@@ -5792,9 +5854,7 @@ finish_struct_1 (tree t)
n_fields = count_fields (TYPE_FIELDS (t));
if (n_fields > 7)
{
- struct sorted_fields_type *field_vec = ggc_alloc_sorted_fields_type
- (sizeof (struct sorted_fields_type) + n_fields * sizeof (tree));
- field_vec->len = n_fields;
+ struct sorted_fields_type *field_vec = sorted_fields_type_new (n_fields);
add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0);
qsort (field_vec->elts, n_fields, sizeof (tree),
field_decl_cmp);
@@ -6062,10 +6122,13 @@ fixed_type_or_null (tree instance, int *nonnull, int *cdtorp)
if (nonnull)
*nonnull = 1;
- /* if we're in a ctor or dtor, we know our type. */
- if (DECL_LANG_SPECIFIC (current_function_decl)
- && (DECL_CONSTRUCTOR_P (current_function_decl)
- || DECL_DESTRUCTOR_P (current_function_decl)))
+ /* if we're in a ctor or dtor, we know our type. If
+ current_class_ptr is set but we aren't in a function, we're in
+ an NSDMI (and therefore a constructor). */
+ if (current_scope () != current_function_decl
+ || (DECL_LANG_SPECIFIC (current_function_decl)
+ && (DECL_CONSTRUCTOR_P (current_function_decl)
+ || DECL_DESTRUCTOR_P (current_function_decl))))
{
if (cdtorp)
*cdtorp = 1;
@@ -6804,8 +6867,8 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
else
{
if (flags & tf_error)
- error ("argument of type %qT does not match %qT",
- TREE_TYPE (rhs), lhstype);
+ error ("cannot convert %qE from type %qT to type %qT",
+ rhs, TREE_TYPE (rhs), lhstype);
return error_mark_node;
}
}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 1866b81f802..035fdcd2f4e 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -267,6 +267,7 @@ cp_common_init_ts (void)
MARK_TS_TYPED (CONST_CAST_EXPR);
MARK_TS_TYPED (STATIC_CAST_EXPR);
MARK_TS_TYPED (DYNAMIC_CAST_EXPR);
+ MARK_TS_TYPED (IMPLICIT_CONV_EXPR);
MARK_TS_TYPED (TEMPLATE_ID_EXPR);
MARK_TS_TYPED (ARROW_EXPR);
MARK_TS_TYPED (SIZEOF_EXPR);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index bb1b753c71b..4eec9f97c7d 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -250,6 +250,7 @@ DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", tcc_unary, 1)
DEFTREECODE (CONST_CAST_EXPR, "const_cast_expr", tcc_unary, 1)
DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", tcc_unary, 1)
DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", tcc_unary, 1)
+DEFTREECODE (IMPLICIT_CONV_EXPR, "implicit_conv_expr", tcc_unary, 1)
DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", tcc_expression, 2)
DEFTREECODE (TYPEID_EXPR, "typeid_expr", tcc_expression, 1)
DEFTREECODE (NOEXCEPT_EXPR, "noexcept_expr", tcc_unary, 1)
@@ -461,6 +462,10 @@ DEFTREECODE (DECLTYPE_TYPE, "decltype_type", tcc_type, 0)
UNDERLYING_TYPE_TYPE is the type in question. */
DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)
+/* A type designated by one of the bases type traits.
+ BASES_TYPE is the type in question. */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
/* Used to represent the template information stored by template
specializations.
The accessors are:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7e5aac750f3..d0e874bc370 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -72,6 +72,7 @@ c-common.h, not after.
DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE)
VEC_INIT_EXPR_IS_CONSTEXPR (in VEC_INIT_EXPR)
DECL_OVERRIDE_P (in FUNCTION_DECL)
+ IMPLICIT_CONV_EXPR_DIRECT_INIT (in IMPLICIT_CONV_EXPR)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -200,6 +201,9 @@ c-common.h, not after.
#define VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK(NODE) \
TREE_CHECK4(NODE,VAR_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL)
+#define VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK(NODE) \
+ TREE_CHECK5(NODE,VAR_DECL,FIELD_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL)
+
#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
@@ -560,6 +564,8 @@ struct GTY (()) tree_argument_pack_select {
typedef enum cp_trait_kind
{
+ CPTK_BASES,
+ CPTK_DIRECT_BASES,
CPTK_HAS_NOTHROW_ASSIGN,
CPTK_HAS_NOTHROW_CONSTRUCTOR,
CPTK_HAS_NOTHROW_COPY,
@@ -670,6 +676,12 @@ enum cp_lambda_default_capture_mode_type {
#define LAMBDA_EXPR_PENDING_PROXIES(NODE) \
(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->pending_proxies)
+/* The closure type of the lambda. Note that the TREE_TYPE of a
+ LAMBDA_EXPR is always NULL_TREE, because we need to instantiate the
+ LAMBDA_EXPR in order to instantiate the type. */
+#define LAMBDA_EXPR_CLOSURE(NODE) \
+ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->closure)
+
struct GTY (()) tree_lambda_expr
{
struct tree_typed typed;
@@ -677,6 +689,7 @@ struct GTY (()) tree_lambda_expr
tree this_capture;
tree return_type;
tree extra_scope;
+ tree closure;
VEC(tree,gc)* pending_proxies;
location_t locus;
enum cp_lambda_default_capture_mode_type default_capture_mode;
@@ -1052,8 +1065,8 @@ struct GTY(()) language_function {
BOOL_BITFIELD returns_value : 1;
BOOL_BITFIELD returns_null : 1;
BOOL_BITFIELD returns_abnormally : 1;
- BOOL_BITFIELD in_function_try_handler : 1;
- BOOL_BITFIELD in_base_initializer : 1;
+ BOOL_BITFIELD x_in_function_try_handler : 1;
+ BOOL_BITFIELD x_in_base_initializer : 1;
/* True if this function can throw an exception. */
BOOL_BITFIELD can_throw : 1;
@@ -1120,9 +1133,9 @@ struct GTY(()) language_function {
cp_function_chain->returns_abnormally
/* Nonzero if we are processing a base initializer. Zero elsewhere. */
-#define in_base_initializer cp_function_chain->in_base_initializer
+#define in_base_initializer cp_function_chain->x_in_base_initializer
-#define in_function_try_handler cp_function_chain->in_function_try_handler
+#define in_function_try_handler cp_function_chain->x_in_function_try_handler
/* Expression always returned from function, or error_mark_node
otherwise, for use by the automatic named return value optimization. */
@@ -2548,7 +2561,7 @@ extern void decl_shadowed_for_var_insert (tree, tree);
global function f. In this case, DECL_TEMPLATE_INFO for S<int>::f
will be non-NULL, but DECL_USE_TEMPLATE will be zero. */
#define DECL_TEMPLATE_INFO(NODE) \
- (DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
+ (DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK (NODE)) \
->u.min.template_info)
/* For a VAR_DECL, indicates that the variable is actually a
@@ -2693,7 +2706,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
template <class T> struct S { friend void f<int>(int, double); }
the DECL_TI_TEMPLATE will be an IDENTIFIER_NODE for `f' and the
- DECL_TI_ARGS will be {int}. */
+ DECL_TI_ARGS will be {int}.
+
+ For a FIELD_DECL with a non-static data member initializer, this value
+ is the FIELD_DECL it was instantiated from. */
#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
/* The template arguments used to obtain this decl from the most
@@ -3233,6 +3249,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
B b{1,2}, not B b({1,2}) or B b = {1,2}. */
#define CONSTRUCTOR_IS_DIRECT_INIT(NODE) (TREE_LANG_FLAG_0 (CONSTRUCTOR_CHECK (NODE)))
+/* True if NODE represents a conversion for direct-initialization in a
+ template. Set by perform_implicit_conversion_flags. */
+#define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \
+ (TREE_LANG_FLAG_0 (IMPLICIT_CONV_EXPR_CHECK (NODE)))
+
/* Nonzero means that an object of this type can not be initialized using
an initializer list. */
#define CLASSTYPE_NON_AGGREGATE(NODE) \
@@ -3414,6 +3435,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define UNDERLYING_TYPE_TYPE(NODE) \
(TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))
+/* The type in question for BASES. */
+#define BASES_TYPE(NODE) \
+ (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+#define BASES_DIRECT(NODE) \
+ TREE_LANG_FLAG_0 (BASES_CHECK (NODE))
+
/* The expression in question for a DECLTYPE_TYPE. */
#define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))
@@ -4842,6 +4870,8 @@ extern bool type_has_constexpr_default_constructor (tree);
extern bool type_has_virtual_destructor (tree);
extern bool type_has_move_constructor (tree);
extern bool type_has_move_assign (tree);
+extern bool type_has_user_declared_move_constructor (tree);
+extern bool type_has_user_declared_move_assign(tree);
extern bool type_build_ctor_call (tree);
extern void explain_non_literal_class (tree);
extern void defaulted_late_check (tree);
@@ -5097,6 +5127,7 @@ extern tree create_temporary_var (tree);
extern void initialize_vtbl_ptrs (tree);
extern tree build_java_class_ref (tree);
extern tree integral_constant_value (tree);
+extern tree decl_constant_value_safe (tree);
extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool);
/* in lex.c */
@@ -5442,6 +5473,9 @@ extern tree finish_id_expression (tree, tree, tree,
location_t);
extern tree finish_typeof (tree);
extern tree finish_underlying_type (tree);
+extern tree calculate_bases (tree);
+extern tree finish_bases (tree, bool);
+extern tree calculate_direct_bases (tree);
extern tree finish_offsetof (tree);
extern void finish_decl_cleanup (tree, tree);
extern void finish_eh_cleanup (tree);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index c5f1ac02cad..708afc8cdc2 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -830,6 +830,7 @@ pp_cxx_cast_expression (cxx_pretty_printer *pp, tree t)
switch (TREE_CODE (t))
{
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
pp_cxx_type_id (pp, TREE_TYPE (t));
pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
break;
@@ -1084,6 +1085,7 @@ pp_cxx_expression (cxx_pretty_printer *pp, tree t)
break;
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
pp_cxx_cast_expression (pp, t);
break;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 30f92dae243..a21cf461aab 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1357,11 +1357,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (DECL_BUILT_IN_CLASS (olddecl) == BUILT_IN_NORMAL
&& DECL_ANTICIPATED (olddecl)
&& TREE_NOTHROW (newdecl)
- && !TREE_NOTHROW (olddecl)
- && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != NULL_TREE
- && built_in_decls [DECL_FUNCTION_CODE (olddecl)] != olddecl
- && types_match)
- TREE_NOTHROW (built_in_decls [DECL_FUNCTION_CODE (olddecl)]) = 1;
+ && !TREE_NOTHROW (olddecl))
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (olddecl);
+ tree tmpdecl = builtin_decl_explicit (fncode);
+ if (tmpdecl && tmpdecl != olddecl && types_match)
+ TREE_NOTHROW (tmpdecl) = 1;
+ }
/* Whether or not the builtin can throw exceptions has no
bearing on this declarator. */
@@ -1540,8 +1542,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
error_at (DECL_SOURCE_LOCATION (newdecl), errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
- ? "%q+#D previously defined here"
- : "%q+#D previously declared here", olddecl);
+ ? G_("%q+#D previously defined here")
+ : G_("%q+#D previously declared here"), olddecl);
return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -2136,17 +2138,21 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
regardless of declaration matches. */
COPY_DECL_RTL (olddecl, newdecl);
if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
- switch (DECL_FUNCTION_CODE (newdecl))
- {
- /* If a compatible prototype of these builtin functions
- is seen, assume the runtime implements it with the
- expected semantics. */
- case BUILT_IN_STPCPY:
- implicit_built_in_decls[DECL_FUNCTION_CODE (newdecl)]
- = built_in_decls[DECL_FUNCTION_CODE (newdecl)];
- default:
- break;
- }
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+ switch (fncode)
+ {
+ /* If a compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with the
+ expected semantics. */
+ case BUILT_IN_STPCPY:
+ if (builtin_decl_explicit_p (fncode))
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ break;
+ }
+ }
}
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -2677,7 +2683,8 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
tree new_decls, old_decls = (b == level ? names : NULL_TREE);
for (new_decls = b->names; new_decls != old_decls;
- new_decls = DECL_CHAIN (new_decls))
+ new_decls = (DECL_P (new_decls) ? DECL_CHAIN (new_decls)
+ : TREE_CHAIN (new_decls)))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
@@ -3229,8 +3236,8 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
if (!t)
{
if (complain & tf_error)
- error (want_template ? "no class template named %q#T in %q#T"
- : "no type named %q#T in %q#T", name, context);
+ error (want_template ? G_("no class template named %q#T in %q#T")
+ : G_("no type named %q#T in %q#T"), name, context);
return error_mark_node;
}
@@ -3648,7 +3655,7 @@ cxx_init_decl_processing (void)
current_lang_name = lang_name_cplusplus;
{
- tree newattrs;
+ tree newattrs, extvisattr;
tree newtype, deltype;
tree ptr_ftype_sizetype;
tree new_eh_spec;
@@ -3678,12 +3685,15 @@ cxx_init_decl_processing (void)
/* Ensure attribs.c is initialized. */
init_attributes ();
- newattrs
- = build_tree_list (get_identifier ("alloc_size"),
- build_tree_list (NULL_TREE, integer_one_node));
+ extvisattr = build_tree_list (get_identifier ("externally_visible"),
+ NULL_TREE);
+ newattrs = tree_cons (get_identifier ("alloc_size"),
+ build_tree_list (NULL_TREE, integer_one_node),
+ extvisattr);
newtype = cp_build_type_attribute_variant (ptr_ftype_sizetype, newattrs);
newtype = build_exception_variant (newtype, new_eh_spec);
- deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
+ deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
+ deltype = build_exception_variant (deltype, empty_except_spec);
push_cp_library_fn (NEW_EXPR, newtype);
push_cp_library_fn (VEC_NEW_EXPR, newtype);
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
@@ -7418,6 +7428,12 @@ grokfndecl (tree ctype,
error ("definition of implicitly-declared %qD", old_decl);
return NULL_TREE;
}
+ else if (DECL_DEFAULTED_FN (old_decl))
+ {
+ error ("definition of explicitly-defaulted %q+D", decl);
+ error ("%q+#D explicitly defaulted here", old_decl);
+ return NULL_TREE;
+ }
/* Since we've smashed OLD_DECL to its
DECL_TEMPLATE_RESULT, we must do the same to DECL. */
@@ -9127,13 +9143,13 @@ grokdeclarator (const cp_declarator *declarator,
virtual. A constructor may not be static. */
if (staticp == 2)
error ((flags == DTOR_FLAG)
- ? "destructor cannot be static member function"
- : "constructor cannot be static member function");
+ ? G_("destructor cannot be static member function")
+ : G_("constructor cannot be static member function"));
if (memfn_quals)
{
error ((flags == DTOR_FLAG)
- ? "destructors may not be cv-qualified"
- : "constructors may not be cv-qualified");
+ ? G_("destructors may not be cv-qualified")
+ : G_("constructors may not be cv-qualified"));
memfn_quals = TYPE_UNQUALIFIED;
}
@@ -9486,8 +9502,10 @@ grokdeclarator (const cp_declarator *declarator,
&& (!friendp || funcdef_flag))
{
error (funcdef_flag
- ? "cannot define member function %<%T::%s%> within %<%T%>"
- : "cannot declare member function %<%T::%s%> within %<%T%>",
+ ? G_("cannot define member function %<%T::%s%> "
+ "within %<%T%>")
+ : G_("cannot declare member function %<%T::%s%> "
+ "within %<%T%>"),
ctype, name, current_class_type);
return error_mark_node;
}
@@ -10207,8 +10225,8 @@ grokdeclarator (const cp_declarator *declarator,
|| sfk == sfk_destructor)
{
error (funcdef_flag
- ? "%qs defined in a non-class scope"
- : "%qs declared in a non-class scope", name);
+ ? G_("%qs defined in a non-class scope")
+ : G_("%qs declared in a non-class scope"), name);
sfk = sfk_none;
}
}
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 4d12a0dd43d..c6110b220fa 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2052,6 +2052,7 @@ dump_expr (tree t, int flags)
break;
CASE_CONVERT:
+ case IMPLICIT_CONV_EXPR:
case VIEW_CONVERT_EXPR:
{
tree op = TREE_OPERAND (t, 0);
@@ -2768,7 +2769,7 @@ static void
cp_diagnostic_starter (diagnostic_context *context,
diagnostic_info *diagnostic)
{
- diagnostic_report_current_module (context);
+ diagnostic_report_current_module (context, diagnostic->location);
cp_print_error_function (context, diagnostic);
maybe_print_instantiation_context (context);
maybe_print_constexpr_context (context);
@@ -2778,8 +2779,9 @@ cp_diagnostic_starter (diagnostic_context *context,
static void
cp_diagnostic_finalizer (diagnostic_context *context,
- diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
+ diagnostic_info *diagnostic)
{
+ virt_loc_aware_diagnostic_finalizer (context, diagnostic);
pp_base_destroy_prefix (context->printer);
}
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index ceec858be1f..e529685c992 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -140,7 +140,7 @@ build_eh_type_type (tree type)
tree
build_exc_ptr (void)
{
- return build_call_n (built_in_decls [BUILT_IN_EH_POINTER],
+ return build_call_n (builtin_decl_explicit (BUILT_IN_EH_POINTER),
1, integer_zero_node);
}
@@ -333,7 +333,7 @@ choose_personality_routine (enum languages lang)
case lang_java:
state = chose_java;
- terminate_node = built_in_decls [BUILT_IN_ABORT];
+ terminate_node = builtin_decl_explicit (BUILT_IN_ABORT);
pragma_java_exceptions = true;
break;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index f246286e767..4561979f72a 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -497,11 +497,11 @@ perform_member_init (tree member, tree init)
mem-initializer for this field. */
if (init == NULL_TREE)
{
- if (CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (member)))
+ if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
/* Do deferred instantiation of the NSDMI. */
init = (tsubst_copy_and_build
- (DECL_INITIAL (member),
- CLASSTYPE_TI_ARGS (DECL_CONTEXT (member)),
+ (DECL_INITIAL (DECL_TI_TEMPLATE (member)),
+ DECL_TI_ARGS (member),
tf_warning_or_error, member, /*function_p=*/false,
/*integral_constant_expression_p=*/false));
else
@@ -1588,27 +1588,25 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
that's value-initialization. */
if (init == void_type_node)
{
- /* If there's a user-provided constructor, we just call that. */
- if (type_has_user_provided_constructor (type))
- /* Fall through. */;
- /* If there isn't, but we still need to call the constructor,
- zero out the object first. */
- else if (type_build_ctor_call (type))
+ /* If no user-provided ctor, we need to zero out the object. */
+ if (!type_has_user_provided_constructor (type))
{
- init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
+ tree field_size = NULL_TREE;
+ if (exp != true_exp && CLASSTYPE_AS_BASE (type) != type)
+ /* Don't clobber already initialized virtual bases. */
+ field_size = TYPE_SIZE (CLASSTYPE_AS_BASE (type));
+ init = build_zero_init_1 (type, NULL_TREE, /*static_storage_p=*/false,
+ field_size);
init = build2 (INIT_EXPR, type, exp, init);
finish_expr_stmt (init);
- /* And then call the constructor. */
}
+
/* If we don't need to mess with the constructor at all,
- then just zero out the object and we're done. */
- else
- {
- init = build2 (INIT_EXPR, type, exp,
- build_value_init_noctor (type, complain));
- finish_expr_stmt (init);
- return;
- }
+ then we're done. */
+ if (! type_build_ctor_call (type))
+ return;
+
+ /* Otherwise fall through and call the constructor. */
init = NULL_TREE;
}
@@ -1794,10 +1792,11 @@ build_offset_ref (tree type, tree member, bool address_p)
constant initializer, return the initializer (or, its initializers,
recursively); otherwise, return DECL. If INTEGRAL_P, the
initializer is only returned if DECL is an integral
- constant-expression. */
+ constant-expression. If RETURN_AGGREGATE_CST_OK_P, it is ok to
+ return an aggregate constant. */
static tree
-constant_value_1 (tree decl, bool integral_p)
+constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
{
while (TREE_CODE (decl) == CONST_DECL
|| (integral_p
@@ -1834,12 +1833,13 @@ constant_value_1 (tree decl, bool integral_p)
if (!init
|| !TREE_TYPE (init)
|| !TREE_CONSTANT (init)
- || (!integral_p
- /* Do not return an aggregate constant (of which
- string literals are a special case), as we do not
- want to make inadvertent copies of such entities,
- and we must be sure that their addresses are the
- same everywhere. */
+ || (!integral_p && !return_aggregate_cst_ok_p
+ /* Unless RETURN_AGGREGATE_CST_OK_P is true, do not
+ return an aggregate constant (of which string
+ literals are a special case), as we do not want
+ to make inadvertent copies of such entities, and
+ we must be sure that their addresses are the
+ same everywhere. */
&& (TREE_CODE (init) == CONSTRUCTOR
|| TREE_CODE (init) == STRING_CST)))
break;
@@ -1856,18 +1856,28 @@ constant_value_1 (tree decl, bool integral_p)
tree
integral_constant_value (tree decl)
{
- return constant_value_1 (decl, /*integral_p=*/true);
+ return constant_value_1 (decl, /*integral_p=*/true,
+ /*return_aggregate_cst_ok_p=*/false);
}
/* A more relaxed version of integral_constant_value, used by the
- common C/C++ code and by the C++ front end for optimization
- purposes. */
+ common C/C++ code. */
tree
decl_constant_value (tree decl)
{
- return constant_value_1 (decl,
- /*integral_p=*/processing_template_decl);
+ return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
+ /*return_aggregate_cst_ok_p=*/true);
+}
+
+/* A version of integral_constant_value used by the C++ front end for
+ optimization purposes. */
+
+tree
+decl_constant_value_safe (tree decl)
+{
+ return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
+ /*return_aggregate_cst_ok_p=*/false);
}
/* Common subroutines of build_new and build_vec_delete. */
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 1316dfb6a83..bb58312b689 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1016,43 +1016,49 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
}
else if (sfk == sfk_constructor)
{
- bool bad = true;
+ bool bad;
+
+ if (DECL_INITIAL (field))
+ {
+ if (msg && DECL_INITIAL (field) == error_mark_node)
+ inform (0, "initializer for %q+#D is invalid", field);
+ if (trivial_p)
+ *trivial_p = false;
+#if 0
+ /* Core 1351: If the field has an NSDMI that could throw, the
+ default constructor is noexcept(false). FIXME this is
+ broken by deferred parsing and 1360 saying we can't lazily
+ declare a non-trivial default constructor. Also this
+ needs to do deferred instantiation. Disable until the
+ conflict between 1351 and 1360 is resolved. */
+ if (spec_p && !expr_noexcept_p (DECL_INITIAL (field), complain))
+ *spec_p = noexcept_false_spec;
+#endif
+
+ /* Don't do the normal processing. */
+ continue;
+ }
+
+ bad = false;
if (CP_TYPE_CONST_P (mem_type)
&& default_init_uninitialized_part (mem_type))
{
if (msg)
error ("uninitialized non-static const member %q#D",
field);
+ bad = true;
}
else if (TREE_CODE (mem_type) == REFERENCE_TYPE)
{
if (msg)
error ("uninitialized non-static reference member %q#D",
field);
+ bad = true;
}
- else
- bad = false;
if (bad && deleted_p)
*deleted_p = true;
- if (DECL_INITIAL (field))
- {
- if (msg && DECL_INITIAL (field) == error_mark_node)
- inform (0, "initializer for %q+#D is invalid", field);
- if (trivial_p)
- *trivial_p = false;
- /* Core 1351: If the field has an NSDMI that could throw, the
- default constructor is noexcept(false). FIXME this is
- broken by deferred parsing and 1360 saying we can't
- lazily declare a non-trivial default constructor. */
- if (spec_p && !expr_noexcept_p (DECL_INITIAL (field), complain))
- *spec_p = noexcept_false_spec;
-
- /* Don't do the normal processing. */
- continue;
- }
-
/* For an implicitly-defined default constructor to be constexpr,
every member must have a user-provided default constructor or
an explicit initializer. */
@@ -1369,18 +1375,31 @@ maybe_explain_implicit_delete (tree decl)
{
informed = true;
if (sfk == sfk_constructor)
- error ("a lambda closure type has a deleted default constructor");
+ inform (DECL_SOURCE_LOCATION (decl),
+ "a lambda closure type has a deleted default constructor");
else if (sfk == sfk_copy_assignment)
- error ("a lambda closure type has a deleted copy assignment operator");
+ inform (DECL_SOURCE_LOCATION (decl),
+ "a lambda closure type has a deleted copy assignment operator");
else
informed = false;
}
+ else if (DECL_ARTIFICIAL (decl)
+ && (sfk == sfk_copy_assignment
+ || sfk == sfk_copy_constructor)
+ && (type_has_user_declared_move_constructor (ctype)
+ || type_has_user_declared_move_assign (ctype)))
+ {
+ inform (0, "%q+#D is implicitly declared as deleted because %qT "
+ "declares a move constructor or move assignment operator",
+ decl, ctype);
+ informed = true;
+ }
if (!informed)
{
tree parm_type = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (decl));
bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
tree scope = push_scope (ctype);
- error ("%qD is implicitly deleted because the default "
+ inform (0, "%q+#D is implicitly deleted because the default "
"definition would be ill-formed:", decl);
pop_scope (scope);
synthesized_method_walk (ctype, sfk, const_p,
@@ -1737,6 +1756,15 @@ lazily_declare_fn (special_function_kind sfk, tree type)
/* Declare the function. */
fn = implicitly_declare_fn (sfk, type, const_p);
+ /* [class.copy]/8 If the class definition declares a move constructor or
+ move assignment operator, the implicitly declared copy constructor is
+ defined as deleted.... */
+ if ((sfk == sfk_copy_assignment
+ || sfk == sfk_copy_constructor)
+ && (type_has_user_declared_move_constructor (type)
+ || type_has_user_declared_move_assign (type)))
+ DECL_DELETED_FN (fn) = true;
+
/* For move variants, rather than declare them as deleted we just
don't declare them at all. */
if (DECL_DELETED_FN (fn)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 83d7b71c8c4..8d138fb7b53 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -210,7 +210,6 @@ static void cp_lexer_commit_tokens
(cp_lexer *);
static void cp_lexer_rollback_tokens
(cp_lexer *);
-#ifdef ENABLE_CHECKING
static void cp_lexer_print_token
(FILE *, cp_token *);
static inline bool cp_lexer_debugging_p
@@ -219,15 +218,6 @@ static void cp_lexer_start_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
static void cp_lexer_stop_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
-#else
-/* If we define cp_lexer_debug_stream to NULL it will provoke warnings
- about passing NULL to functions that require non-NULL arguments
- (fputs, fprintf). It will never be used, so all we need is a value
- of the right type that's guaranteed not to be NULL. */
-#define cp_lexer_debug_stream stdout
-#define cp_lexer_print_token(str, tok) (void) 0
-#define cp_lexer_debugging_p(lexer) 0
-#endif /* ENABLE_CHECKING */
static cp_token_cache *cp_token_cache_new
(cp_token *, cp_token *);
@@ -241,33 +231,64 @@ static void cp_parser_initial_pragma
/* Variables. */
-#ifdef ENABLE_CHECKING
/* The stream to which debugging output should be written. */
static FILE *cp_lexer_debug_stream;
-#endif /* ENABLE_CHECKING */
/* Nonzero if we are parsing an unevaluated operand: an operand to
sizeof, typeof, or alignof. */
int cp_unevaluated_operand;
-#ifdef ENABLE_CHECKING
-/* Dump up to NUM tokens in BUFFER to FILE. If NUM is 0, dump all the
- tokens. */
+/* Dump up to NUM tokens in BUFFER to FILE starting with token
+ START_TOKEN. If START_TOKEN is NULL, the dump starts with the
+ first token in BUFFER. If NUM is 0, dump all the tokens. If
+ CURR_TOKEN is set and it is one of the tokens in BUFFER, it will be
+ highlighted by surrounding it in [[ ]]. */
-void
-cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num)
+static void
+cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer,
+ cp_token *start_token, unsigned num,
+ cp_token *curr_token)
{
- unsigned i;
+ unsigned i, nprinted;
cp_token *token;
+ bool do_print;
fprintf (file, "%u tokens\n", VEC_length (cp_token, buffer));
+ if (buffer == NULL)
+ return;
+
if (num == 0)
num = VEC_length (cp_token, buffer);
- for (i = 0; VEC_iterate (cp_token, buffer, i, token) && i < num; i++)
+ if (start_token == NULL)
+ start_token = VEC_address (cp_token, buffer);
+
+ if (start_token > VEC_address (cp_token, buffer))
+ {
+ cp_lexer_print_token (file, VEC_index (cp_token, buffer, 0));
+ fprintf (file, " ... ");
+ }
+
+ do_print = false;
+ nprinted = 0;
+ for (i = 0; VEC_iterate (cp_token, buffer, i, token) && nprinted < num; i++)
{
+ if (token == start_token)
+ do_print = true;
+
+ if (!do_print)
+ continue;
+
+ nprinted++;
+ if (token == curr_token)
+ fprintf (file, "[[");
+
cp_lexer_print_token (file, token);
+
+ if (token == curr_token)
+ fprintf (file, "]]");
+
switch (token->type)
{
case CPP_SEMICOLON:
@@ -298,9 +319,227 @@ cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num)
void
cp_lexer_debug_tokens (VEC(cp_token,gc) *buffer)
{
- cp_lexer_dump_tokens (stderr, buffer, 0);
+ cp_lexer_dump_tokens (stderr, buffer, NULL, 0, NULL);
+}
+
+
+/* Dump the cp_parser tree field T to FILE if T is non-NULL. DESC is the
+ description for T. */
+
+static void
+cp_debug_print_tree_if_set (FILE *file, const char *desc, tree t)
+{
+ if (t)
+ {
+ fprintf (file, "%s: ", desc);
+ print_node_brief (file, "", t, 0);
+ }
+}
+
+
+/* Dump parser context C to FILE. */
+
+static void
+cp_debug_print_context (FILE *file, cp_parser_context *c)
+{
+ const char *status_s[] = { "OK", "ERROR", "COMMITTED" };
+ fprintf (file, "{ status = %s, scope = ", status_s[c->status]);
+ print_node_brief (file, "", c->object_type, 0);
+ fprintf (file, "}\n");
+}
+
+
+/* Print the stack of parsing contexts to FILE starting with FIRST. */
+
+static void
+cp_debug_print_context_stack (FILE *file, cp_parser_context *first)
+{
+ unsigned i;
+ cp_parser_context *c;
+
+ fprintf (file, "Parsing context stack:\n");
+ for (i = 0, c = first; c; c = c->next, i++)
+ {
+ fprintf (file, "\t#%u: ", i);
+ cp_debug_print_context (file, c);
+ }
+}
+
+
+/* Print the value of FLAG to FILE. DESC is a string describing the flag. */
+
+static void
+cp_debug_print_flag (FILE *file, const char *desc, bool flag)
+{
+ if (flag)
+ fprintf (file, "%s: true\n", desc);
+}
+
+
+/* Print an unparsed function entry UF to FILE. */
+
+static void
+cp_debug_print_unparsed_function (FILE *file, cp_unparsed_functions_entry *uf)
+{
+ unsigned i;
+ cp_default_arg_entry *default_arg_fn;
+ tree fn;
+
+ fprintf (file, "\tFunctions with default args:\n");
+ for (i = 0;
+ VEC_iterate (cp_default_arg_entry, uf->funs_with_default_args, i,
+ default_arg_fn);
+ i++)
+ {
+ fprintf (file, "\t\tClass type: ");
+ print_node_brief (file, "", default_arg_fn->class_type, 0);
+ fprintf (file, "\t\tDeclaration: ");
+ print_node_brief (file, "", default_arg_fn->decl, 0);
+ fprintf (file, "\n");
+ }
+
+ fprintf (file, "\n\tFunctions with definitions that require "
+ "post-processing\n\t\t");
+ for (i = 0; VEC_iterate (tree, uf->funs_with_definitions, i, fn); i++)
+ {
+ print_node_brief (file, "", fn, 0);
+ fprintf (file, " ");
+ }
+ fprintf (file, "\n");
+
+ fprintf (file, "\n\tNon-static data members with initializers that require "
+ "post-processing\n\t\t");
+ for (i = 0; VEC_iterate (tree, uf->nsdmis, i, fn); i++)
+ {
+ print_node_brief (file, "", fn, 0);
+ fprintf (file, " ");
+ }
+ fprintf (file, "\n");
+}
+
+
+/* Print the stack of unparsed member functions S to FILE. */
+
+static void
+cp_debug_print_unparsed_queues (FILE *file,
+ VEC(cp_unparsed_functions_entry, gc) *s)
+{
+ unsigned i;
+ cp_unparsed_functions_entry *uf;
+
+ fprintf (file, "Unparsed functions\n");
+ for (i = 0; VEC_iterate (cp_unparsed_functions_entry, s, i, uf); i++)
+ {
+ fprintf (file, "#%u:\n", i);
+ cp_debug_print_unparsed_function (file, uf);
+ }
+}
+
+
+/* Dump the tokens in a window of size WINDOW_SIZE around the next_token for
+ the given PARSER. If FILE is NULL, the output is printed on stderr. */
+
+static void
+cp_debug_parser_tokens (FILE *file, cp_parser *parser, int window_size)
+{
+ cp_token *next_token, *first_token, *start_token;
+
+ if (file == NULL)
+ file = stderr;
+
+ next_token = parser->lexer->next_token;
+ first_token = VEC_address (cp_token, parser->lexer->buffer);
+ start_token = (next_token > first_token + window_size / 2)
+ ? next_token - window_size / 2
+ : first_token;
+ cp_lexer_dump_tokens (file, parser->lexer->buffer, start_token, window_size,
+ next_token);
+}
+
+
+/* Dump debugging information for the given PARSER. If FILE is NULL,
+ the output is printed on stderr. */
+
+void
+cp_debug_parser (FILE *file, cp_parser *parser)
+{
+ const size_t window_size = 20;
+ cp_token *token;
+ expanded_location eloc;
+
+ if (file == NULL)
+ file = stderr;
+
+ fprintf (file, "Parser state\n\n");
+ fprintf (file, "Number of tokens: %u\n",
+ VEC_length (cp_token, parser->lexer->buffer));
+ cp_debug_print_tree_if_set (file, "Lookup scope", parser->scope);
+ cp_debug_print_tree_if_set (file, "Object scope",
+ parser->object_scope);
+ cp_debug_print_tree_if_set (file, "Qualifying scope",
+ parser->qualifying_scope);
+ cp_debug_print_context_stack (file, parser->context);
+ cp_debug_print_flag (file, "Allow GNU extensions",
+ parser->allow_gnu_extensions_p);
+ cp_debug_print_flag (file, "'>' token is greater-than",
+ parser->greater_than_is_operator_p);
+ cp_debug_print_flag (file, "Default args allowed in current "
+ "parameter list", parser->default_arg_ok_p);
+ cp_debug_print_flag (file, "Parsing integral constant-expression",
+ parser->integral_constant_expression_p);
+ cp_debug_print_flag (file, "Allow non-constant expression in current "
+ "constant-expression",
+ parser->allow_non_integral_constant_expression_p);
+ cp_debug_print_flag (file, "Seen non-constant expression",
+ parser->non_integral_constant_expression_p);
+ cp_debug_print_flag (file, "Local names and 'this' forbidden in "
+ "current context",
+ parser->local_variables_forbidden_p);
+ cp_debug_print_flag (file, "In unbraced linkage specification",
+ parser->in_unbraced_linkage_specification_p);
+ cp_debug_print_flag (file, "Parsing a declarator",
+ parser->in_declarator_p);
+ cp_debug_print_flag (file, "In template argument list",
+ parser->in_template_argument_list_p);
+ cp_debug_print_flag (file, "Parsing an iteration statement",
+ parser->in_statement & IN_ITERATION_STMT);
+ cp_debug_print_flag (file, "Parsing a switch statement",
+ parser->in_statement & IN_SWITCH_STMT);
+ cp_debug_print_flag (file, "Parsing a structured OpenMP block",
+ parser->in_statement & IN_OMP_BLOCK);
+ cp_debug_print_flag (file, "Parsing a an OpenMP loop",
+ parser->in_statement & IN_OMP_FOR);
+ cp_debug_print_flag (file, "Parsing an if statement",
+ parser->in_statement & IN_IF_STMT);
+ cp_debug_print_flag (file, "Parsing a type-id in an expression "
+ "context", parser->in_type_id_in_expr_p);
+ cp_debug_print_flag (file, "Declarations are implicitly extern \"C\"",
+ parser->implicit_extern_c);
+ cp_debug_print_flag (file, "String expressions should be translated "
+ "to execution character set",
+ parser->translate_strings_p);
+ cp_debug_print_flag (file, "Parsing function body outside of a "
+ "local class", parser->in_function_body);
+ cp_debug_print_flag (file, "Auto correct a colon to a scope operator",
+ parser->colon_corrects_to_scope_p);
+ if (parser->type_definition_forbidden_message)
+ fprintf (file, "Error message for forbidden type definitions: %s\n",
+ parser->type_definition_forbidden_message);
+ cp_debug_print_unparsed_queues (file, parser->unparsed_queues);
+ fprintf (file, "Number of class definitions in progress: %u\n",
+ parser->num_classes_being_defined);
+ fprintf (file, "Number of template parameter lists for the current "
+ "declaration: %u\n", parser->num_template_parameter_lists);
+ cp_debug_parser_tokens (file, parser, window_size);
+ token = parser->lexer->next_token;
+ fprintf (file, "Next token to parse:\n");
+ fprintf (file, "\tToken: ");
+ cp_lexer_print_token (file, token);
+ eloc = expand_location (token->location);
+ fprintf (file, "\n\tFile: %s\n", eloc.file);
+ fprintf (file, "\tLine: %d\n", eloc.line);
+ fprintf (file, "\tColumn: %d\n", eloc.column);
}
-#endif
/* Allocate memory for a new lexer object and return it. */
@@ -315,10 +554,9 @@ cp_lexer_alloc (void)
/* Allocate the memory. */
lexer = ggc_alloc_cleared_cp_lexer ();
-#ifdef ENABLE_CHECKING
/* Initially we are not debugging. */
lexer->debugging_p = false;
-#endif /* ENABLE_CHECKING */
+
lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
CP_SAVED_TOKEN_STACK);
@@ -388,10 +626,8 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
CP_SAVED_TOKEN_STACK);
-#ifdef ENABLE_CHECKING
/* Initially we are not debugging. */
lexer->debugging_p = false;
-#endif
gcc_assert (!lexer->next_token->purged_p);
return lexer;
@@ -409,15 +645,12 @@ cp_lexer_destroy (cp_lexer *lexer)
/* Returns nonzero if debugging information should be output. */
-#ifdef ENABLE_CHECKING
-
static inline bool
cp_lexer_debugging_p (cp_lexer *lexer)
{
return lexer->debugging_p;
}
-#endif /* ENABLE_CHECKING */
static inline cp_token_position
cp_lexer_token_position (cp_lexer *lexer, bool previous_p)
@@ -852,8 +1085,6 @@ cp_lexer_rollback_tokens (cp_lexer* lexer)
/* Print a representation of the TOKEN on the STREAM. */
-#ifdef ENABLE_CHECKING
-
static void
cp_lexer_print_token (FILE * stream, cp_token *token)
{
@@ -914,6 +1145,7 @@ static void
cp_lexer_start_debugging (cp_lexer* lexer)
{
lexer->debugging_p = true;
+ cp_lexer_debug_stream = stderr;
}
/* Stop emitting debugging information. */
@@ -922,10 +1154,9 @@ static void
cp_lexer_stop_debugging (cp_lexer* lexer)
{
lexer->debugging_p = false;
+ cp_lexer_debug_stream = NULL;
}
-#endif /* ENABLE_CHECKING */
-
/* Create a new cp_token_cache, representing a range of tokens. */
static cp_token_cache *
@@ -4521,8 +4752,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
&& (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
== TEMPLATE_ID_EXPR)))
permerror (input_location, TYPE_P (new_scope)
- ? "%qT is not a template"
- : "%qD is not a template",
+ ? G_("%qT is not a template")
+ : G_("%qD is not a template"),
new_scope);
/* If it is a class scope, try to complete it; we are about to
be looking up names inside the class. */
@@ -7304,6 +7535,12 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
case RID_UNDERLYING_TYPE:
kind = CPTK_UNDERLYING_TYPE;
break;
+ case RID_BASES:
+ kind = CPTK_BASES;
+ break;
+ case RID_DIRECT_BASES:
+ kind = CPTK_DIRECT_BASES;
+ break;
default:
gcc_unreachable ();
}
@@ -7348,9 +7585,17 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
/* Complete the trait expression, which may mean either processing
the trait expr now or saving it for template instantiation. */
- return kind != CPTK_UNDERLYING_TYPE
- ? finish_trait_expr (kind, type1, type2)
- : finish_underlying_type (type1);
+ switch(kind)
+ {
+ case CPTK_UNDERLYING_TYPE:
+ return finish_underlying_type (type1);
+ case CPTK_BASES:
+ return finish_bases (type1, false);
+ case CPTK_DIRECT_BASES:
+ return finish_bases (type1, true);
+ default:
+ return finish_trait_expr (kind, type1, type2);
+ }
}
/* Lambdas that appear in variable initializer or default argument scope
@@ -7630,6 +7875,31 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/*ambiguous_decls=*/NULL,
capture_token->location);
+ if (capture_init_expr == error_mark_node)
+ {
+ unqualified_name_lookup_error (capture_id);
+ continue;
+ }
+ else if (DECL_P (capture_init_expr)
+ && (TREE_CODE (capture_init_expr) != VAR_DECL
+ && TREE_CODE (capture_init_expr) != PARM_DECL))
+ {
+ error_at (capture_token->location,
+ "capture of non-variable %qD ",
+ capture_init_expr);
+ inform (0, "%q+#D declared here", capture_init_expr);
+ continue;
+ }
+ if (TREE_CODE (capture_init_expr) == VAR_DECL
+ && decl_storage_duration (capture_init_expr) != dk_auto)
+ {
+ pedwarn (capture_token->location, 0, "capture of variable "
+ "%qD with non-automatic storage duration",
+ capture_init_expr);
+ inform (0, "%q+#D declared here", capture_init_expr);
+ continue;
+ }
+
capture_init_expr
= finish_id_expression
(capture_id,
@@ -7647,10 +7917,6 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
capture_token->location);
}
- if (TREE_CODE (capture_init_expr) == IDENTIFIER_NODE)
- capture_init_expr
- = unqualified_name_lookup_error (capture_init_expr);
-
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
&& !explicit_init_p)
{
@@ -8688,7 +8954,9 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
{
stmt = begin_range_for_stmt (scope, init);
finish_range_for_decl (stmt, range_decl, range_expr);
- if (!type_dependent_expression_p (range_expr))
+ if (!type_dependent_expression_p (range_expr)
+ /* do_auto_deduction doesn't mess with template init-lists. */
+ && !BRACE_ENCLOSED_INITIALIZER_P (range_expr))
do_range_for_auto_deduction (range_decl, range_expr);
}
else
@@ -12017,6 +12285,7 @@ cp_parser_template_argument_list (cp_parser* parser)
parser->integral_constant_expression_p = false;
saved_non_ice_p = parser->non_integral_constant_expression_p;
parser->non_integral_constant_expression_p = false;
+
/* Parse the arguments. */
do
{
@@ -12834,7 +13103,6 @@ cp_parser_simple_type_specifier (cp_parser* parser,
case RID_UNDERLYING_TYPE:
type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
-
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
token->location,
@@ -12842,6 +13110,14 @@ cp_parser_simple_type_specifier (cp_parser* parser,
return type;
+ case RID_BASES:
+ case RID_DIRECT_BASES:
+ type = cp_parser_trait_expr (parser, token->keyword);
+ if (decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs, type,
+ token->location,
+ /*type_definition_p=*/false);
+ return type;
default:
break;
}
@@ -16534,17 +16810,20 @@ cp_parser_parameter_declaration (cp_parser *parser,
if (id_declarator && id_declarator->kind == cdk_id)
error_at (declarator_token_start->location,
- template_parm_p
- ? "template parameter pack %qD"
- " cannot have a default argument"
- : "parameter pack %qD cannot have a default argument",
+ template_parm_p
+ ? G_("template parameter pack %qD "
+ "cannot have a default argument")
+ : G_("parameter pack %qD cannot have "
+ "a default argument"),
id_declarator->u.id.unqualified_name);
else
error_at (declarator_token_start->location,
- template_parm_p
- ? "template parameter pack cannot have a default argument"
- : "parameter pack cannot have a default argument");
-
+ template_parm_p
+ ? G_("template parameter pack cannot have "
+ "a default argument")
+ : G_("parameter pack cannot have a "
+ "default argument"));
+
default_argument = NULL_TREE;
}
}
@@ -20615,7 +20894,8 @@ cp_parser_save_nsdmi (cp_parser* parser)
cp_token *last;
tree node;
- cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0);
+ /* Save tokens until the next comma or semicolon. */
+ cp_parser_cache_group (parser, CPP_COMMA, /*depth=*/0);
last = parser->lexer->next_token;
@@ -20628,7 +20908,7 @@ cp_parser_save_nsdmi (cp_parser* parser)
/* Parse a template-argument-list, as well as the trailing ">" (but
- not the opening ">"). See cp_parser_template_argument_list for the
+ not the opening "<"). See cp_parser_template_argument_list for the
return value. */
static tree
@@ -21717,6 +21997,12 @@ cp_parser_cache_group (cp_parser *parser,
kind of syntax error. */
return true;
+ /* If we're caching something finished by a comma (or semicolon),
+ such as an NSDMI, don't consume the comma. */
+ if (end == CPP_COMMA
+ && (token->type == CPP_SEMICOLON || token->type == CPP_COMMA))
+ return false;
+
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
/* See if it starts a new group. */
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index e08c0b415a0..b44d23cd8cd 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -352,9 +352,7 @@ typedef struct GTY(()) cp_parser {
} cp_parser;
/* In parser.c */
-#ifdef ENABLE_CHECKING
-extern void cp_lexer_dump_tokens (FILE *, VEC(cp_token,gc) *, unsigned);
extern void cp_lexer_debug_tokens (VEC(cp_token,gc) *);
-#endif
+extern void cp_debug_parser (FILE *, cp_parser *);
#endif /* GCC_CP_PARSER_H */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4d57f94d2b1..56fa6324ad4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -165,7 +165,7 @@ static int template_decl_level (tree);
static int check_cv_quals_for_unify (int, tree, tree);
static void template_parm_level_and_index (tree, int*, int*);
static int unify_pack_expansion (tree, tree, tree,
- tree, int, bool, bool, bool);
+ tree, unification_kind_t, bool, bool);
static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
@@ -892,7 +892,8 @@ maybe_process_partial_specialization (tree type)
instantiation. Reassign it to the new member
specialization template. */
spec_entry elt;
- spec_entry **slot;
+ spec_entry *entry;
+ void **slot;
elt.tmpl = most_general_template (tmpl);
elt.args = CLASSTYPE_TI_ARGS (inst);
@@ -903,10 +904,10 @@ maybe_process_partial_specialization (tree type)
elt.tmpl = tmpl;
elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
- slot = (spec_entry **)
- htab_find_slot (type_specializations, &elt, INSERT);
- *slot = ggc_alloc_spec_entry ();
- **slot = elt;
+ slot = htab_find_slot (type_specializations, &elt, INSERT);
+ entry = ggc_alloc_spec_entry ();
+ *entry = elt;
+ *slot = entry;
}
else if (COMPLETE_OR_OPEN_TYPE_P (inst))
/* But if we've had an implicit instantiation, that's a
@@ -1294,7 +1295,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
hashval_t hash)
{
tree fn;
- spec_entry **slot = NULL;
+ void **slot = NULL;
spec_entry elt;
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec));
@@ -1327,10 +1328,10 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
if (hash == 0)
hash = hash_specialization (&elt);
- slot = (spec_entry **)
+ slot =
htab_find_slot_with_hash (decl_specializations, &elt, hash, INSERT);
if (*slot)
- fn = (*slot)->spec;
+ fn = ((spec_entry *) *slot)->spec;
else
fn = NULL_TREE;
}
@@ -1423,11 +1424,12 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
&& !check_specialization_namespace (tmpl))
DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
- if (!optimize_specialization_lookup_p (tmpl))
+ if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
{
+ spec_entry *entry = ggc_alloc_spec_entry ();
gcc_assert (tmpl && args && spec);
- *slot = ggc_alloc_spec_entry ();
- **slot = elt;
+ *entry = elt;
+ *slot = entry;
if (TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
&& PRIMARY_TEMPLATE_P (tmpl)
&& DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
@@ -1589,6 +1591,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
return val;
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
@@ -1639,19 +1642,19 @@ iterative_hash_template_arg (tree arg, hashval_t val)
bool
reregister_specialization (tree spec, tree tinfo, tree new_spec)
{
- spec_entry **slot;
+ spec_entry *entry;
spec_entry elt;
elt.tmpl = most_general_template (TI_TEMPLATE (tinfo));
elt.args = TI_ARGS (tinfo);
elt.spec = NULL_TREE;
- slot = (spec_entry **) htab_find_slot (decl_specializations, &elt, INSERT);
- if (*slot)
+ entry = (spec_entry *) htab_find (decl_specializations, &elt);
+ if (entry != NULL)
{
- gcc_assert ((*slot)->spec == spec || (*slot)->spec == new_spec);
+ gcc_assert (entry->spec == spec || entry->spec == new_spec);
gcc_assert (new_spec != NULL_TREE);
- (*slot)->spec = new_spec;
+ entry->spec = new_spec;
return 1;
}
@@ -2961,6 +2964,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
break;
case TEMPLATE_TYPE_PARM:
+ t = TYPE_MAIN_VARIANT (t);
case TEMPLATE_TEMPLATE_PARM:
if (TEMPLATE_TYPE_PARAMETER_PACK (t))
parameter_pack_p = true;
@@ -2976,6 +2980,9 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
}
break;
+ case BASES:
+ parameter_pack_p = true;
+ break;
default:
/* Not a parameter pack. */
break;
@@ -6741,22 +6748,10 @@ coerce_template_parms (tree parms,
{
if (PACK_EXPANSION_P (arg))
{
- if (complain & tf_error)
- {
- /* FIXME this restriction was removed by N2555; see
- bug 35722. */
- /* If ARG is a pack expansion, but PARM is not a
- template parameter pack (if it were, we would have
- handled it above), we're trying to expand into a
- fixed-length argument list. */
- if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
- sorry ("cannot expand %<%E%> into a fixed-length "
- "argument list", arg);
- else
- sorry ("cannot expand %<%T%> into a fixed-length "
- "argument list", arg);
- }
- ++lost;
+ /* We don't know how many args we have yet, just
+ use the unconverted ones for now. */
+ new_inner_args = args;
+ break;
}
}
else if (require_all_args)
@@ -7053,7 +7048,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
{
tree templ = NULL_TREE, parmlist;
tree t;
- spec_entry **slot;
+ void **slot;
spec_entry *entry;
spec_entry elt;
hashval_t hash;
@@ -7491,10 +7486,11 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
elt.spec = t;
- slot = (spec_entry **) htab_find_slot_with_hash (type_specializations,
- &elt, hash, INSERT);
- *slot = ggc_alloc_spec_entry ();
- **slot = elt;
+ slot = htab_find_slot_with_hash (type_specializations,
+ &elt, hash, INSERT);
+ entry = ggc_alloc_spec_entry ();
+ *entry = elt;
+ *slot = entry;
/* Note this use of the partial instantiation so we can check it
later in maybe_process_partial_specialization. */
@@ -7710,6 +7706,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
case MODOP_EXPR:
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
@@ -9113,10 +9110,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree in_decl)
{
tree pattern;
- tree pack, packs = NULL_TREE, unsubstituted_packs = NULL_TREE;
+ tree pack, packs = NULL_TREE;
+ bool unsubstituted_packs = false;
int i, len = -1;
tree result;
- int incomplete = 0;
htab_t saved_local_specializations = NULL;
gcc_assert (PACK_EXPANSION_P (t));
@@ -9133,6 +9130,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree arg_pack = NULL_TREE;
tree orig_arg = NULL_TREE;
+ if (TREE_CODE (parm_pack) == BASES)
+ {
+ if (BASES_DIRECT (parm_pack))
+ return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain, in_decl, false));
+ else
+ return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain, in_decl, false));
+ }
if (TREE_CODE (parm_pack) == PARM_DECL)
{
if (!cp_unevaluated_operand)
@@ -9189,21 +9195,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
int my_len =
TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack));
- /* It's all-or-nothing with incomplete argument packs. */
- if (incomplete && !ARGUMENT_PACK_INCOMPLETE_P (arg_pack))
- return error_mark_node;
-
+ /* Don't bother trying to do a partial substitution with
+ incomplete packs; we'll try again after deduction. */
if (ARGUMENT_PACK_INCOMPLETE_P (arg_pack))
- incomplete = 1;
+ return t;
if (len < 0)
len = my_len;
else if (len != my_len)
{
- if (incomplete)
- /* We got explicit args for some packs but not others;
- do nothing now and try again after deduction. */
- return t;
if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
error ("mismatched argument pack lengths while expanding "
"%<%T%>",
@@ -9221,10 +9221,11 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
TREE_TYPE (packs) = orig_arg;
}
else
- /* We can't substitute for this parameter pack. */
- unsubstituted_packs = tree_cons (TREE_PURPOSE (pack),
- TREE_VALUE (pack),
- unsubstituted_packs);
+ {
+ /* We can't substitute for this parameter pack. */
+ unsubstituted_packs = true;
+ break;
+ }
}
/* We cannot expand this expansion expression, because we don't have
@@ -9261,8 +9262,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
/* For each argument in each argument pack, substitute into the
pattern. */
- result = make_tree_vec (len + incomplete);
- for (i = 0; i < len + incomplete; ++i)
+ result = make_tree_vec (len);
+ for (i = 0; i < len; ++i)
{
/* For parameter pack, change the substitution of the parameter
pack to the ith argument in its argument pack, then expand
@@ -9270,33 +9271,38 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
for (pack = packs; pack; pack = TREE_CHAIN (pack))
{
tree parm = TREE_PURPOSE (pack);
+ tree arg;
+ /* Select the Ith argument from the pack. */
if (TREE_CODE (parm) == PARM_DECL)
{
- /* Select the Ith argument from the pack. */
- tree arg = make_node (ARGUMENT_PACK_SELECT);
- ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
- ARGUMENT_PACK_SELECT_INDEX (arg) = i;
- mark_used (parm);
- register_local_specialization (arg, parm);
+ if (i == 0)
+ {
+ arg = make_node (ARGUMENT_PACK_SELECT);
+ ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
+ mark_used (parm);
+ register_local_specialization (arg, parm);
+ }
+ else
+ arg = retrieve_local_specialization (parm);
}
else
{
- tree value = parm;
int idx, level;
template_parm_level_and_index (parm, &level, &idx);
-
- if (i < len)
+
+ if (i == 0)
{
- /* Select the Ith argument from the pack. */
- value = make_node (ARGUMENT_PACK_SELECT);
- ARGUMENT_PACK_SELECT_FROM_PACK (value) = TREE_VALUE (pack);
- ARGUMENT_PACK_SELECT_INDEX (value) = i;
+ arg = make_node (ARGUMENT_PACK_SELECT);
+ ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
+ /* Update the corresponding argument. */
+ TMPL_ARG (args, level, idx) = arg;
}
-
- /* Update the corresponding argument. */
- TMPL_ARG (args, level, idx) = value;
+ else
+ /* Re-use the ARGUMENT_PACK_SELECT. */
+ arg = TMPL_ARG (args, level, idx);
}
+ ARGUMENT_PACK_SELECT_INDEX (arg) = i;
}
/* Substitute into the PATTERN with the altered arguments. */
@@ -9307,13 +9313,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
else
TREE_VEC_ELT (result, i) = tsubst (pattern, args, complain, in_decl);
- if (i == len)
- /* When we have incomplete argument packs, the last "expanded"
- result is itself a pack expansion, which allows us
- to deduce more arguments. */
- TREE_VEC_ELT (result, i) =
- make_pack_expansion (TREE_VEC_ELT (result, i));
-
if (TREE_VEC_ELT (result, i) == error_mark_node)
{
result = error_mark_node;
@@ -10282,6 +10281,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
= tsubst_expr (DECL_INITIAL (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
+ else if (DECL_INITIAL (t))
+ {
+ /* Set up DECL_TEMPLATE_INFO so that we can get at the
+ NSDMI in perform_member_init. Still set DECL_INITIAL
+ so that we know there is one. */
+ DECL_INITIAL (r) = void_zero_node;
+ gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
+ retrofit_lang_decl (r);
+ DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
+ }
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE;
@@ -11729,7 +11738,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
- tsubst_expr. */
+ tsubst_copy_and_build or tsubst_expr. */
static tree
tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
@@ -11894,6 +11903,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
+ case CONVERT_EXPR:
case NOP_EXPR:
return build1
(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
@@ -13041,7 +13052,11 @@ tsubst_copy_and_build (tree t,
if (error_msg)
error (error_msg);
if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
- decl = unqualified_name_lookup_error (decl);
+ {
+ if (complain & tf_error)
+ unqualified_name_lookup_error (decl);
+ decl = error_mark_node;
+ }
return decl;
}
@@ -13092,6 +13107,23 @@ tsubst_copy_and_build (tree t,
(tsubst (TREE_TYPE (t), args, complain, in_decl),
RECUR (TREE_OPERAND (t, 0)));
+ case IMPLICIT_CONV_EXPR:
+ {
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree expr = RECUR (TREE_OPERAND (t, 0));
+ int flags = LOOKUP_IMPLICIT;
+ if (IMPLICIT_CONV_EXPR_DIRECT_INIT (t))
+ flags = LOOKUP_NORMAL;
+ return perform_implicit_conversion_flags (type, expr, complain,
+ flags);
+ }
+
+ case CONVERT_EXPR:
+ return build1
+ (CONVERT_EXPR,
+ tsubst (TREE_TYPE (t), args, complain, in_decl),
+ RECUR (TREE_OPERAND (t, 0)));
+
case CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
@@ -13927,8 +13959,8 @@ tsubst_copy_and_build (tree t,
{
tree r = build_lambda_expr ();
- tree type = tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
- TREE_TYPE (r) = type;
+ tree type = tsubst (LAMBDA_EXPR_CLOSURE (t), args, complain, NULL_TREE);
+ LAMBDA_EXPR_CLOSURE (r) = type;
CLASSTYPE_LAMBDA_EXPR (type) = r;
LAMBDA_EXPR_LOCATION (r)
@@ -14289,6 +14321,40 @@ pop_deduction_access_scope (tree tmpl)
pop_deferring_access_checks ();
}
+/* PARM is a template parameter pack for FN. Returns true iff
+ PARM is used in a deducible way in the argument list of FN. */
+
+static bool
+pack_deducible_p (tree parm, tree fn)
+{
+ tree t = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ for (; t; t = TREE_CHAIN (t))
+ {
+ tree type = TREE_VALUE (t);
+ tree packs;
+ if (!PACK_EXPANSION_P (type))
+ continue;
+ for (packs = PACK_EXPANSION_PARAMETER_PACKS (type);
+ packs; packs = TREE_CHAIN (packs))
+ if (TREE_VALUE (packs) == parm)
+ {
+ /* The template parameter pack is used in a function parameter
+ pack. If this is the end of the parameter list, the
+ template parameter pack is deducible. */
+ if (TREE_CHAIN (t) == void_list_node)
+ return true;
+ else
+ /* Otherwise, not. Well, it could be deduced from
+ a non-pack parameter, but doing so would end up with
+ a deduction mismatch, so don't bother. */
+ return false;
+ }
+ }
+ /* The template parameter pack isn't used in any function parameter
+ packs, but it might be used deeper, e.g. tuple<Args...>. */
+ return true;
+}
+
/* 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
@@ -14334,7 +14400,6 @@ fn_type_unification (tree fn,
tree parms;
tree fntype;
int result;
- bool incomplete_argument_packs_p = false;
gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
@@ -14386,6 +14451,7 @@ fn_type_unification (tree fn,
{
tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
bool parameter_pack = false;
+ tree targ = TREE_VEC_ELT (converted_args, i);
/* Dig out the actual parm. */
if (TREE_CODE (parm) == TYPE_DECL
@@ -14400,16 +14466,15 @@ fn_type_unification (tree fn,
parameter_pack = TEMPLATE_PARM_PARAMETER_PACK (parm);
}
- if (parameter_pack)
- {
- int level, idx;
- tree targ;
- template_parm_level_and_index (parm, &level, &idx);
+ if (!parameter_pack && targ == NULL_TREE)
+ /* No explicit argument for this template parameter. */
+ incomplete = true;
+ if (parameter_pack && pack_deducible_p (parm, fn))
+ {
/* Mark the argument pack as "incomplete". We could
still deduce more arguments during unification.
We remove this mark in type_unification_real. */
- targ = TMPL_ARG (converted_args, level, idx);
if (targ)
{
ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
@@ -14418,18 +14483,10 @@ fn_type_unification (tree fn,
}
/* We have some incomplete argument packs. */
- incomplete_argument_packs_p = true;
+ incomplete = true;
}
}
- if (incomplete_argument_packs_p)
- /* Any substitution is guaranteed to be incomplete if there
- are incomplete argument packs, because we can still deduce
- more arguments. */
- incomplete = 1;
- else
- incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
-
processing_template_decl += incomplete;
fntype = deduction_tsubst_fntype (fn, converted_args,
(explain_p
@@ -14643,6 +14700,134 @@ maybe_adjust_types_for_deduction (unification_kind_t strict,
return result;
}
+/* Subroutine of unify_one_argument. PARM is a function parameter of a
+ template which does contain any deducible template parameters; check if
+ ARG is a suitable match for it. STRICT, FLAGS and EXPLAIN_P are as in
+ unify_one_argument. */
+
+static int
+check_non_deducible_conversion (tree parm, tree arg, int strict,
+ int flags, bool explain_p)
+{
+ tree type;
+
+ if (!TYPE_P (arg))
+ type = TREE_TYPE (arg);
+ else
+ type = arg;
+
+ if (same_type_p (parm, type))
+ return unify_success (explain_p);
+
+ if (strict == DEDUCE_CONV)
+ {
+ if (can_convert_arg (type, parm, NULL_TREE, flags))
+ return unify_success (explain_p);
+ }
+ else if (strict != DEDUCE_EXACT)
+ {
+ if (can_convert_arg (parm, type,
+ TYPE_P (arg) ? NULL_TREE : arg,
+ flags))
+ return unify_success (explain_p);
+ }
+
+ if (strict == DEDUCE_EXACT)
+ return unify_type_mismatch (explain_p, parm, arg);
+ else
+ return unify_arg_conversion (explain_p, parm, type, arg);
+}
+
+/* Subroutine of type_unification_real and unify_pack_expansion to
+ handle unification of a single P/A pair. Parameters are as
+ for those functions. */
+
+static int
+unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
+ int subr, unification_kind_t strict, int flags,
+ bool explain_p)
+{
+ tree arg_expr = NULL_TREE;
+ int arg_strict;
+
+ if (arg == error_mark_node || parm == error_mark_node)
+ return unify_invalid (explain_p);
+ if (arg == unknown_type_node)
+ /* We can't deduce anything from this, but we might get all the
+ template args from other function args. */
+ return unify_success (explain_p);
+
+ /* FIXME uses_deducible_template_parms */
+ if (TYPE_P (parm) && !uses_template_parms (parm))
+ return check_non_deducible_conversion (parm, arg, strict, flags,
+ explain_p);
+
+ switch (strict)
+ {
+ case DEDUCE_CALL:
+ arg_strict = (UNIFY_ALLOW_OUTER_LEVEL
+ | UNIFY_ALLOW_MORE_CV_QUAL
+ | UNIFY_ALLOW_DERIVED);
+ break;
+
+ case DEDUCE_CONV:
+ arg_strict = UNIFY_ALLOW_LESS_CV_QUAL;
+ break;
+
+ case DEDUCE_EXACT:
+ arg_strict = UNIFY_ALLOW_NONE;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* We only do these transformations if this is the top-level
+ parameter_type_list in a call or declaration matching; in other
+ situations (nested function declarators, template argument lists) we
+ won't be comparing a type to an expression, and we don't do any type
+ adjustments. */
+ if (!subr)
+ {
+ if (!TYPE_P (arg))
+ {
+ gcc_assert (TREE_TYPE (arg) != NULL_TREE);
+ if (type_unknown_p (arg))
+ {
+ /* [temp.deduct.type] A template-argument can be
+ deduced from a pointer to function or pointer
+ to member function argument if the set of
+ overloaded functions does not contain function
+ templates and at most one of a set of
+ overloaded functions provides a unique
+ match. */
+
+ if (resolve_overloaded_unification
+ (tparms, targs, parm, arg, strict,
+ arg_strict, explain_p))
+ return unify_success (explain_p);
+ return unify_overload_resolution_failure (explain_p, arg);
+ }
+
+ arg_expr = arg;
+ arg = unlowered_expr_type (arg);
+ if (arg == error_mark_node)
+ return unify_invalid (explain_p);
+ }
+
+ arg_strict |=
+ maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr);
+ }
+ else
+ gcc_assert ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL)
+ == (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL));
+
+ /* For deduction from an init-list we need the actual list. */
+ if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
+ arg = arg_expr;
+ return unify (tparms, targs, parm, arg, arg_strict, explain_p);
+}
+
/* Most parms like fn_type_unification.
If SUBR is 1, we're being called recursively (to unify the
@@ -14660,10 +14845,9 @@ type_unification_real (tree tparms,
int flags,
bool explain_p)
{
- tree parm, arg, arg_expr;
+ tree parm, arg;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
- int sub_strict;
int saw_undeduced = 0;
tree parms;
const tree *args;
@@ -14678,25 +14862,6 @@ type_unification_real (tree tparms,
in TARGS. */
NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE;
- switch (strict)
- {
- case DEDUCE_CALL:
- sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL
- | UNIFY_ALLOW_DERIVED);
- break;
-
- case DEDUCE_CONV:
- sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
- break;
-
- case DEDUCE_EXACT:
- sub_strict = UNIFY_ALLOW_NONE;
- break;
-
- default:
- gcc_unreachable ();
- }
-
again:
parms = xparms;
args = xargs;
@@ -14726,90 +14891,12 @@ type_unification_real (tree tparms,
arg = args[ia];
++ia;
- arg_expr = NULL;
-
- if (arg == error_mark_node)
- return unify_invalid (explain_p);
- if (arg == unknown_type_node)
- /* We can't deduce anything from this, but we might get all the
- template args from other function args. */
- continue;
-
- /* Conversions will be performed on a function argument that
- corresponds with a function parameter that contains only
- non-deducible template parameters and explicitly specified
- template parameters. */
- if (!uses_template_parms (parm))
- {
- tree type;
-
- if (!TYPE_P (arg))
- type = TREE_TYPE (arg);
- else
- type = arg;
-
- if (same_type_p (parm, type))
- continue;
- if (strict == DEDUCE_CONV)
- {
- if (can_convert_arg (type, parm, NULL_TREE, flags))
- continue;
- }
- else if (strict != DEDUCE_EXACT)
- {
- if (can_convert_arg (parm, type,
- TYPE_P (arg) ? NULL_TREE : arg,
- flags))
- continue;
- }
-
- if (strict == DEDUCE_EXACT)
- return unify_type_mismatch (explain_p, parm, arg);
- else
- return unify_arg_conversion (explain_p, parm, type, arg);
- }
-
- if (!TYPE_P (arg))
- {
- gcc_assert (TREE_TYPE (arg) != NULL_TREE);
- if (type_unknown_p (arg))
- {
- /* [temp.deduct.type]
- A template-argument can be deduced from a pointer to
- function or pointer to member function argument if
- the set of overloaded functions does not contain
- function templates and at most one of a set of
- overloaded functions provides a unique match. */
- if (resolve_overloaded_unification
- (tparms, targs, parm, arg, strict, sub_strict, explain_p))
- continue;
-
- return unify_overload_resolution_failure (explain_p, arg);
- }
- arg_expr = arg;
- arg = unlowered_expr_type (arg);
- if (arg == error_mark_node)
- return unify_invalid (explain_p);
- }
-
- {
- int arg_strict = sub_strict;
-
- if (!subr)
- arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
- arg_expr);
-
- if (arg == init_list_type_node && arg_expr)
- arg = arg_expr;
- if (unify (tparms, targs, parm, arg, arg_strict, explain_p))
- /* If unification failed, the recursive call will have updated
- UI appropriately. */
- return 1;
- }
+ if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
+ flags, explain_p))
+ return 1;
}
-
if (parms
&& parms != void_list_node
&& TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
@@ -14826,7 +14913,7 @@ type_unification_real (tree tparms,
/* Copy the parameter into parmvec. */
TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
if (unify_pack_expansion (tparms, targs, parmvec, argvec, strict,
- /*call_args_p=*/true, /*subr=*/subr, explain_p))
+ /*subr=*/subr, explain_p))
return 1;
/* Advance to the end of the list of parameters. */
@@ -15461,10 +15548,12 @@ template_parm_level_and_index (tree parm, int* level, int* index)
unify. CALL_ARGS_P is true iff PACKED_ARGS is actually a function
call argument list. We'll need to adjust the arguments to make them
types. SUBR tells us if this is from a recursive call to
- type_unification_real. */
+ type_unification_real, or for comparing two template argument
+ lists. */
+
static int
unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
- tree packed_args, int strict, bool call_args_p,
+ tree packed_args, unification_kind_t strict,
bool subr, bool explain_p)
{
tree parm
@@ -15495,92 +15584,56 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
unified and unify each with the pattern. */
for (i = start; i < len; i++)
{
- tree parm = pattern;
+ tree parm;
+ bool any_explicit = false;
+ tree arg = TREE_VEC_ELT (packed_args, i);
- /* For each parameter pack, clear out the deduced value so that
- we can deduce it again. */
+ /* For each parameter pack, set its TMPL_ARG to either NULL_TREE
+ or the element of its argument pack at the current index if
+ this argument was explicitly specified. */
for (pack = packs; pack; pack = TREE_CHAIN (pack))
{
int idx, level;
+ tree arg, pargs;
template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx);
- TMPL_ARG (targs, level, idx) = NULL_TREE;
+ arg = NULL_TREE;
+ if (TREE_VALUE (pack)
+ && (pargs = ARGUMENT_PACK_EXPLICIT_ARGS (TREE_VALUE (pack)))
+ && (i < TREE_VEC_LENGTH (pargs)))
+ {
+ any_explicit = true;
+ arg = TREE_VEC_ELT (pargs, i);
+ }
+ TMPL_ARG (targs, level, idx) = arg;
}
- /* Unify the pattern with the current argument. */
- {
- tree arg = TREE_VEC_ELT (packed_args, i);
- tree arg_expr = NULL_TREE;
- int arg_strict = strict;
-
- if (call_args_p)
- {
- int sub_strict;
-
- /* This mirrors what we do in type_unification_real. */
- switch (strict)
- {
- case DEDUCE_CALL:
- sub_strict = (UNIFY_ALLOW_OUTER_LEVEL
- | UNIFY_ALLOW_MORE_CV_QUAL
- | UNIFY_ALLOW_DERIVED);
- break;
-
- case DEDUCE_CONV:
- sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
- break;
-
- case DEDUCE_EXACT:
- sub_strict = UNIFY_ALLOW_NONE;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- if (!TYPE_P (arg))
- {
- gcc_assert (TREE_TYPE (arg) != NULL_TREE);
- if (type_unknown_p (arg))
- {
- /* [temp.deduct.type] A template-argument can be
- deduced from a pointer to function or pointer
- to member function argument if the set of
- overloaded functions does not contain function
- templates and at most one of a set of
- overloaded functions provides a unique
- match. */
-
- if (resolve_overloaded_unification
- (tparms, targs, parm, arg,
- (unification_kind_t) strict,
- sub_strict, explain_p))
- goto unified;
- return unify_overload_resolution_failure (explain_p, arg);
- }
-
- arg_expr = arg;
- arg = unlowered_expr_type (arg);
- if (arg == error_mark_node)
- return unify_invalid (explain_p);
- }
-
- arg_strict = sub_strict;
-
- if (!subr)
- arg_strict |=
- maybe_adjust_types_for_deduction ((unification_kind_t) strict,
- &parm, &arg, arg_expr);
- }
+ /* If we had explicit template arguments, substitute them into the
+ pattern before deduction. */
+ if (any_explicit)
+ {
+ /* Some arguments might still be unspecified or dependent. */
+ bool dependent;
+ ++processing_template_decl;
+ dependent = any_dependent_template_arguments_p (targs);
+ if (!dependent)
+ --processing_template_decl;
+ parm = tsubst (pattern, targs,
+ explain_p ? tf_warning_or_error : tf_none,
+ NULL_TREE);
+ if (dependent)
+ --processing_template_decl;
+ if (parm == error_mark_node)
+ return 1;
+ }
+ else
+ parm = pattern;
- /* For deduction from an init-list we need the actual list. */
- if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
- arg = arg_expr;
- RECUR_AND_CHECK_FAILURE (tparms, targs, parm, arg, arg_strict,
- explain_p);
- }
+ /* Unify the pattern with the current argument. */
+ if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
+ LOOKUP_IMPLICIT, explain_p))
+ return 1;
- unified:
/* For each parameter pack, collect the deduced value. */
for (pack = packs; pack; pack = TREE_CHAIN (pack))
{
@@ -15619,21 +15672,12 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
if (old_pack && ARGUMENT_PACK_INCOMPLETE_P (old_pack))
{
- /* Prepend the explicit arguments onto NEW_ARGS. */
+ /* If we had fewer function args than explicit template args,
+ just use the explicits. */
tree explicit_args = ARGUMENT_PACK_EXPLICIT_ARGS (old_pack);
- tree old_args = new_args;
- int i, explicit_len = TREE_VEC_LENGTH (explicit_args);
- int len = explicit_len + TREE_VEC_LENGTH (old_args);
-
- /* Copy the explicit arguments. */
- new_args = make_tree_vec (len);
- for (i = 0; i < explicit_len; i++)
- TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (explicit_args, i);
-
- /* Copy the deduced arguments. */
- for (; i < len; i++)
- TREE_VEC_ELT (new_args, i) =
- TREE_VEC_ELT (old_args, i - explicit_len);
+ int explicit_len = TREE_VEC_LENGTH (explicit_args);
+ if (len < explicit_len)
+ new_args = explicit_args;
}
if (!old_pack)
@@ -15961,9 +16005,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
if (parm_variadic_p
&& unify_pack_expansion (tparms, targs,
parmvec, argvec,
- UNIFY_ALLOW_NONE,
- /*call_args_p=*/false,
- /*subr=*/false, explain_p))
+ DEDUCE_EXACT,
+ /*subr=*/true, explain_p))
return 1;
}
arg = TYPE_TI_TEMPLATE (arg);
@@ -16253,17 +16296,55 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
case TREE_VEC:
{
- int i;
+ int i, len, argslen;
+ int parm_variadic_p = 0;
+
if (TREE_CODE (arg) != TREE_VEC)
return unify_template_argument_mismatch (explain_p, parm, arg);
- if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
- return unify_arity (explain_p, TREE_VEC_LENGTH (arg),
- TREE_VEC_LENGTH (parm));
- for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
- RECUR_AND_CHECK_FAILURE (tparms, targs,
- TREE_VEC_ELT (parm, i),
- TREE_VEC_ELT (arg, i),
- UNIFY_ALLOW_NONE, explain_p);
+
+ len = TREE_VEC_LENGTH (parm);
+ argslen = TREE_VEC_LENGTH (arg);
+
+ /* Check for pack expansions in the parameters. */
+ for (i = 0; i < len; ++i)
+ {
+ if (PACK_EXPANSION_P (TREE_VEC_ELT (parm, i)))
+ {
+ if (i == len - 1)
+ /* We can unify against something with a trailing
+ parameter pack. */
+ parm_variadic_p = 1;
+ else
+ /* [temp.deduct.type]/9: If the template argument list of
+ P contains a pack expansion that is not the last
+ template argument, the entire template argument list
+ is a non-deduced context. */
+ return unify_success (explain_p);
+ }
+ }
+
+ /* If we don't have enough arguments to satisfy the parameters
+ (not counting the pack expression at the end), or we have
+ too many arguments for a parameter list that doesn't end in
+ a pack expression, we can't unify. */
+ if (parm_variadic_p
+ ? argslen < len - parm_variadic_p
+ : argslen != len)
+ return unify_arity (explain_p, TREE_VEC_LENGTH (arg), len);
+
+ /* Unify all of the parameters that precede the (optional)
+ pack expression. */
+ for (i = 0; i < len - parm_variadic_p; ++i)
+ {
+ RECUR_AND_CHECK_FAILURE (tparms, targs,
+ TREE_VEC_ELT (parm, i),
+ TREE_VEC_ELT (arg, i),
+ UNIFY_ALLOW_NONE, explain_p);
+ }
+ if (parm_variadic_p)
+ return unify_pack_expansion (tparms, targs, parm, arg,
+ DEDUCE_EXACT,
+ /*subr=*/true, explain_p);
return unify_success (explain_p);
}
@@ -16425,58 +16506,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
- {
- tree packed_parms = ARGUMENT_PACK_ARGS (parm);
- tree packed_args = ARGUMENT_PACK_ARGS (arg);
- int i, len = TREE_VEC_LENGTH (packed_parms);
- int argslen = TREE_VEC_LENGTH (packed_args);
- int parm_variadic_p = 0;
-
- for (i = 0; i < len; ++i)
- {
- if (PACK_EXPANSION_P (TREE_VEC_ELT (packed_parms, i)))
- {
- if (i == len - 1)
- /* We can unify against something with a trailing
- parameter pack. */
- parm_variadic_p = 1;
- else
- /* Since there is something following the pack
- expansion, we cannot unify this template argument
- list. */
- return unify_success (explain_p);
- }
- }
-
-
- /* If we don't have enough arguments to satisfy the parameters
- (not counting the pack expression at the end), or we have
- too many arguments for a parameter list that doesn't end in
- a pack expression, we can't unify. */
- if (argslen < (len - parm_variadic_p))
- return unify_too_few_arguments (explain_p, argslen, len);
- if (argslen > len && !parm_variadic_p)
- return unify_too_many_arguments (explain_p, argslen, len);
-
- /* Unify all of the parameters that precede the (optional)
- pack expression. */
- for (i = 0; i < len - parm_variadic_p; ++i)
- {
- RECUR_AND_CHECK_FAILURE (tparms, targs,
- TREE_VEC_ELT (packed_parms, i),
- TREE_VEC_ELT (packed_args, i),
- strict, explain_p);
- }
-
- if (parm_variadic_p)
- return unify_pack_expansion (tparms, targs,
- packed_parms, packed_args,
- strict, /*call_args_p=*/false,
- /*subr=*/false, explain_p);
- return unify_success (explain_p);
- }
-
- break;
+ return unify (tparms, targs, ARGUMENT_PACK_ARGS (parm),
+ ARGUMENT_PACK_ARGS (arg), strict, explain_p);
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
@@ -16785,9 +16816,8 @@ more_specialized_fn (tree pat1, tree pat2, int len)
TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
deduce1 = (unify_pack_expansion (tparms1, targs1, parmvec,
- argvec, UNIFY_ALLOW_NONE,
- /*call_args_p=*/false,
- /*subr=*/0, /*explain_p=*/false)
+ argvec, DEDUCE_EXACT,
+ /*subr=*/true, /*explain_p=*/false)
== 0);
/* We cannot deduce in the other direction, because ARG1 is
@@ -16810,9 +16840,8 @@ more_specialized_fn (tree pat1, tree pat2, int len)
TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
deduce2 = (unify_pack_expansion (tparms2, targs2, parmvec,
- argvec, UNIFY_ALLOW_NONE,
- /*call_args_p=*/false,
- /*subr=*/0, /*explain_p=*/false)
+ argvec, DEDUCE_EXACT,
+ /*subr=*/true, /*explain_p=*/false)
== 0);
/* We cannot deduce in the other direction, because ARG2 is
@@ -18016,6 +18045,8 @@ instantiate_decl (tree d, int defer_ok,
d = DECL_CLONED_FUNCTION (d);
if (DECL_TEMPLATE_INSTANTIATED (d)
+ || (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_DEFAULTED_FN (d) && DECL_INITIAL (d))
|| DECL_TEMPLATE_SPECIALIZATION (d))
/* D has already been instantiated or explicitly specialized, so
there's nothing for us to do here.
@@ -19190,6 +19221,7 @@ type_dependent_expression_p (tree expression)
|| TREE_CODE (expression) == STATIC_CAST_EXPR
|| TREE_CODE (expression) == CONST_CAST_EXPR
|| TREE_CODE (expression) == REINTERPRET_CAST_EXPR
+ || TREE_CODE (expression) == IMPLICIT_CONV_EXPR
|| TREE_CODE (expression) == CAST_EXPR)
return dependent_type_p (TREE_TYPE (expression));
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 7ad1e8d5ebd..42195be4a81 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-objc.h"
#include "tree-inline.h"
#include "tree-mudflap.h"
+#include "intl.h"
#include "toplev.h"
#include "flags.h"
#include "output.h"
@@ -2985,8 +2986,8 @@ finish_id_expression (tree id_expression,
else
{
error (TREE_CODE (decl) == VAR_DECL
- ? "use of %<auto%> variable from containing function"
- : "use of parameter from containing function");
+ ? G_("use of %<auto%> variable from containing function")
+ : G_("use of parameter from containing function"));
error (" %q+#D declared here", decl);
return error_mark_node;
}
@@ -3394,6 +3395,149 @@ finish_underlying_type (tree type)
return underlying_type;
}
+/* Implement the __direct_bases keyword: Return the direct base classes
+ of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+ VEC(tree, gc) *vector = make_tree_vector();
+ tree bases_vec = NULL_TREE;
+ VEC(tree, none) *base_binfos;
+ tree binfo;
+ unsigned i;
+
+ complete_type (type);
+
+ if (!NON_UNION_CLASS_TYPE_P (type))
+ return make_tree_vec (0);
+
+ base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+ /* Virtual bases are initialized first */
+ for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+ {
+ if (BINFO_VIRTUAL_P (binfo))
+ {
+ VEC_safe_push (tree, gc, vector, binfo);
+ }
+ }
+
+ /* Now non-virtuals */
+ for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+ {
+ if (!BINFO_VIRTUAL_P (binfo))
+ {
+ VEC_safe_push (tree, gc, vector, binfo);
+ }
+ }
+
+
+ bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+ for (i = 0; i < VEC_length (tree, vector); ++i)
+ {
+ TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+ }
+ return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+ of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_)
+{
+ /* Don't walk bases of virtual bases */
+ return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+ VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+ if (!BINFO_VIRTUAL_P (binfo))
+ {
+ VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+ }
+ return NULL_TREE;
+}
+
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+ VEC(tree, gc) *vector = make_tree_vector();
+
+ /* Now add non-virtual base classes in order of construction */
+ dfs_walk_all (TYPE_BINFO (type),
+ dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+ return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+ VEC(tree, gc) *vector = make_tree_vector();
+ tree bases_vec = NULL_TREE;
+ unsigned i;
+ VEC(tree, gc) *vbases;
+ VEC(tree, gc) *nonvbases;
+ tree binfo;
+
+ complete_type (type);
+
+ if (!NON_UNION_CLASS_TYPE_P (type))
+ return make_tree_vec (0);
+
+ /* First go through virtual base classes */
+ for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+ VEC_iterate (tree, vbases, i, binfo); i++)
+ {
+ VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+ VEC_safe_splice (tree, gc, vector, vbase_bases);
+ release_tree_vector (vbase_bases);
+ }
+
+ /* Now for the non-virtual bases */
+ nonvbases = calculate_bases_helper (type);
+ VEC_safe_splice (tree, gc, vector, nonvbases);
+ release_tree_vector (nonvbases);
+
+ /* Last element is entire class, so don't copy */
+ bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+ for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+ {
+ TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+ }
+ release_tree_vector (vector);
+ return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+ tree bases = NULL_TREE;
+
+ if (!processing_template_decl)
+ {
+ /* Parameter packs can only be used in templates */
+ error ("Parameter pack __bases only valid in template declaration");
+ return error_mark_node;
+ }
+
+ bases = cxx_make_type (BASES);
+ BASES_TYPE (bases) = type;
+ BASES_DIRECT (bases) = direct;
+ SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+ return bases;
+}
+
/* Perform C++-specific checks for __builtin_offsetof before calling
fold_offsetof. */
@@ -4784,7 +4928,7 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
void
finish_omp_barrier (void)
{
- tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
@@ -4794,7 +4938,7 @@ finish_omp_barrier (void)
void
finish_omp_flush (void)
{
- tree fn = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE];
+ tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
@@ -4804,7 +4948,7 @@ finish_omp_flush (void)
void
finish_omp_taskwait (void)
{
- tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
@@ -4814,7 +4958,7 @@ finish_omp_taskwait (void)
void
finish_omp_taskyield (void)
{
- tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD];
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
VEC(tree,gc) *vec = make_tree_vector ();
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
@@ -5210,23 +5354,20 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
}
}
-/* Returns true if TYPE is a complete type, an array of unknown bound,
- or (possibly cv-qualified) void, returns false otherwise. */
+/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
+ void, or a complete type, returns it, otherwise NULL_TREE. */
-static bool
+static tree
check_trait_type (tree type)
{
- if (COMPLETE_TYPE_P (type))
- return true;
-
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))
- return true;
+ return type;
if (VOID_TYPE_P (type))
- return true;
+ return type;
- return false;
+ return complete_type_or_else (strip_array_types (type), NULL_TREE);
}
/* Process a trait expression. */
@@ -5276,10 +5417,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5298,20 +5435,15 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
if (!check_trait_type (type1))
- {
- error ("incomplete type %qT not allowed", type1);
- return error_mark_node;
- }
+ return error_mark_node;
break;
case CPTK_IS_BASE_OF:
if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
&& !same_type_ignoring_top_level_qualifiers_p (type1, type2)
- && !COMPLETE_TYPE_P (type2))
- {
- error ("incomplete type %qT not allowed", type2);
- return error_mark_node;
- }
+ && !complete_type_or_else (type2, NULL_TREE))
+ /* We already issued an error. */
+ return error_mark_node;
break;
case CPTK_IS_CLASS:
@@ -7481,8 +7613,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
return t;
case LAMBDA_EXPR:
- case DYNAMIC_CAST_EXPR:
- case PSEUDO_DTOR_EXPR:
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
@@ -8023,6 +8153,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
return (potential_constant_expression_1
(TREE_OPERAND (t, 0),
TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
@@ -8210,7 +8341,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return false;
default:
- sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]);
+ sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]);
gcc_unreachable();
return false;
}
@@ -8325,7 +8456,7 @@ build_lambda_object (tree lambda_expr)
/* N2927: "[The closure] class type is not an aggregate."
But we briefly treat it as an aggregate to make this simpler. */
- type = TREE_TYPE (lambda_expr);
+ type = LAMBDA_EXPR_CLOSURE (lambda_expr);
CLASSTYPE_NON_AGGREGATE (type) = 0;
expr = finish_compound_literal (type, expr, tf_warning_or_error);
CLASSTYPE_NON_AGGREGATE (type) = 1;
@@ -8366,7 +8497,7 @@ begin_lambda_type (tree lambda)
type = begin_class_definition (type, /*attributes=*/NULL_TREE);
/* Cross-reference the expression and the type. */
- TREE_TYPE (lambda) = type;
+ LAMBDA_EXPR_CLOSURE (lambda) = type;
CLASSTYPE_LAMBDA_EXPR (type) = lambda;
return type;
@@ -8400,7 +8531,7 @@ lambda_function (tree lambda)
{
tree type;
if (TREE_CODE (lambda) == LAMBDA_EXPR)
- type = TREE_TYPE (lambda);
+ type = LAMBDA_EXPR_CLOSURE (lambda);
else
type = lambda;
gcc_assert (LAMBDA_TYPE_P (type));
@@ -8715,7 +8846,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
/* If TREE_TYPE isn't set, we're still in the introducer, so check
for duplicates. */
- if (!TREE_TYPE (lambda))
+ if (!LAMBDA_EXPR_CLOSURE (lambda))
{
if (IDENTIFIER_MARKED (name))
{
@@ -8741,13 +8872,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
/* Add it to the appropriate closure class if we've started it. */
- if (current_class_type && current_class_type == TREE_TYPE (lambda))
+ if (current_class_type
+ && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
finish_member_declaration (member);
LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
- if (TREE_TYPE (lambda))
+ if (LAMBDA_EXPR_CLOSURE (lambda))
return build_capture_proxy (member);
/* For explicit captures we haven't started the function yet, so we wait
and build the proxy from cp_parser_lambda_body. */
@@ -8790,7 +8922,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
{
tree lambda = TREE_VALUE (node);
- current_class_type = TREE_TYPE (lambda);
+ current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
var = add_capture (lambda,
id,
initializer,
@@ -8821,7 +8953,7 @@ lambda_expr_this_capture (tree lambda)
if (!this_capture
&& LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
{
- tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda));
+ tree containing_function = TYPE_CONTEXT (LAMBDA_EXPR_CLOSURE (lambda));
tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
tree init = NULL_TREE;
@@ -8871,7 +9003,8 @@ lambda_expr_this_capture (tree lambda)
else
{
/* To make sure that current_class_ref is for the lambda. */
- gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
+ gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
+ == LAMBDA_EXPR_CLOSURE (lambda));
result = this_capture;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f23b888f376..d023eb86cb8 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1879,8 +1879,12 @@ bot_manip (tree* tp, int* walk_subtrees, void* data)
tree u;
if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
- u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
- tf_warning_or_error);
+ {
+ u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
+ tf_warning_or_error);
+ if (AGGR_INIT_ZERO_FIRST (TREE_OPERAND (t, 1)))
+ AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true;
+ }
else
u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t),
tf_warning_or_error);
@@ -2384,6 +2388,7 @@ cp_tree_equal (tree t1, tree t2)
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
case NEW_EXPR:
if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
return false;
@@ -2994,6 +2999,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
case STATIC_CAST_EXPR:
case CONST_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
if (TREE_TYPE (*tp))
WALK_SUBTREE (TREE_TYPE (*tp));
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d416b42db3b..749aa3f5ac9 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1827,7 +1827,7 @@ decay_conversion (tree exp)
/* FIXME remove? at least need to remember that this isn't really a
constant expression if EXP isn't decl_constant_var_p, like with
C_MAYBE_CONST_EXPR. */
- exp = decl_constant_value (exp);
+ exp = decl_constant_value_safe (exp);
if (error_operand_p (exp))
return error_mark_node;
@@ -2128,8 +2128,16 @@ build_class_member_access_expr (tree object, tree member,
if (!CLASS_TYPE_P (object_type))
{
if (complain & tf_error)
- error ("request for member %qD in %qE, which is of non-class type %qT",
- member, object, object_type);
+ {
+ if (POINTER_TYPE_P (object_type)
+ && CLASS_TYPE_P (TREE_TYPE (object_type)))
+ error ("request for member %qD in %qE, which is of pointer "
+ "type %qT (maybe you meant to use %<->%> ?)",
+ member, object, object_type);
+ else
+ error ("request for member %qD in %qE, which is of non-class "
+ "type %qT", member, object, object_type);
+ }
return error_mark_node;
}
@@ -2508,8 +2516,16 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
if (!CLASS_TYPE_P (object_type))
{
if (complain & tf_error)
- error ("request for member %qD in %qE, which is of non-class type %qT",
- name, object, object_type);
+ {
+ if (POINTER_TYPE_P (object_type)
+ && CLASS_TYPE_P (TREE_TYPE (object_type)))
+ error ("request for member %qD in %qE, which is of pointer "
+ "type %qT (maybe you meant to use %<->%> ?)",
+ name, object, object_type);
+ else
+ error ("request for member %qD in %qE, which is of non-class "
+ "type %qT", name, object, object_type);
+ }
return error_mark_node;
}
@@ -2591,7 +2607,9 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
if (member == NULL_TREE)
{
if (complain & tf_error)
- error ("%qD has no member named %qE", object_type, name);
+ error ("%qD has no member named %qE",
+ TREE_CODE (access_path) == TREE_BINFO
+ ? TREE_TYPE (access_path) : object_type, name);
return error_mark_node;
}
if (member == error_mark_node)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 96b95c2b5ce..3accab62133 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -340,7 +340,10 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
type);
FOR_EACH_VEC_ELT (tree, pure, ix, fn)
- inform (input_location, "\t%+#D", fn);
+ if (! DECL_CLONED_FUNCTION_P (fn)
+ || DECL_COMPLETE_DESTRUCTOR_P (fn))
+ inform (input_location, "\t%+#D", fn);
+
/* Now truncate the vector. This leaves it non-null, so we know
there are pure virtuals, but empty so we don't list them out
again. */
diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c
index 9b1495feb94..fabf314a024 100644
--- a/gcc/cppdefault.c
+++ b/gcc/cppdefault.c
@@ -1,6 +1,7 @@
/* CPP Library.
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2003, 2004, 2006, 2007, 2010 Free Software Foundation, Inc.
+ 1999, 2000, 2003, 2004, 2006, 2007, 2010, 2011
+ Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -25,18 +26,12 @@
#include "tm.h"
#include "cppdefault.h"
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
-#endif
-
-#ifndef STANDARD_INCLUDE_COMPONENT
-#define STANDARD_INCLUDE_COMPONENT 0
+#ifndef NATIVE_SYSTEM_HEADER_COMPONENT
+#define NATIVE_SYSTEM_HEADER_COMPONENT 0
#endif
#if defined (CROSS_DIRECTORY_STRUCTURE) && !defined (TARGET_SYSTEM_ROOT)
# undef LOCAL_INCLUDE_DIR
-# undef SYSTEM_INCLUDE_DIR
-# undef STANDARD_INCLUDE_DIR
#else
# undef CROSS_INCLUDE_DIR
#endif
@@ -89,14 +84,8 @@ const struct default_include cpp_include_defaults[]
/* Another place the target system's headers might be. */
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0 },
#endif
-#ifdef SYSTEM_INCLUDE_DIR
- /* Some systems have an extra dir of include files. */
- { SYSTEM_INCLUDE_DIR, 0, 0, 0, 1, 0 },
-#endif
-#ifdef STANDARD_INCLUDE_DIR
/* /usr/include comes dead last. */
- { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 1, 0 },
-#endif
+ { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 0, 0 }
};
#endif /* no INCLUDE_DEFAULTS */
@@ -136,4 +125,3 @@ cpp_relocated (void)
return relocated;
}
-
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d297cdda0ca..a8c0e669352 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -255,9 +255,9 @@ diagnostic_action_after_output (diagnostic_context *context,
}
void
-diagnostic_report_current_module (diagnostic_context *context)
+diagnostic_report_current_module (diagnostic_context *context, location_t where)
{
- const struct line_map *map;
+ const struct line_map *map = NULL;
if (pp_needs_newline (context->printer))
{
@@ -265,10 +265,13 @@ diagnostic_report_current_module (diagnostic_context *context)
pp_needs_newline (context->printer) = false;
}
- if (input_location <= BUILTINS_LOCATION)
+ if (where <= BUILTINS_LOCATION)
return;
- map = linemap_lookup (line_table, input_location);
+ linemap_resolve_location (line_table, where,
+ LRK_MACRO_DEFINITION_LOCATION,
+ &map);
+
if (map && diagnostic_last_module_changed (context, map))
{
diagnostic_set_last_module (context, map);
@@ -278,18 +281,18 @@ diagnostic_report_current_module (diagnostic_context *context)
if (context->show_column)
pp_verbatim (context->printer,
"In file included from %s:%d:%d",
- map->to_file,
+ LINEMAP_FILE (map),
LAST_SOURCE_LINE (map), LAST_SOURCE_COLUMN (map));
else
pp_verbatim (context->printer,
"In file included from %s:%d",
- map->to_file, LAST_SOURCE_LINE (map));
+ LINEMAP_FILE (map), LAST_SOURCE_LINE (map));
while (! MAIN_FILE_P (map))
{
map = INCLUDED_FROM (line_table, map);
pp_verbatim (context->printer,
",\n from %s:%d",
- map->to_file, LAST_SOURCE_LINE (map));
+ LINEMAP_FILE (map), LAST_SOURCE_LINE (map));
}
pp_verbatim (context->printer, ":");
pp_newline (context->printer);
@@ -301,7 +304,7 @@ void
default_diagnostic_starter (diagnostic_context *context,
diagnostic_info *diagnostic)
{
- diagnostic_report_current_module (context);
+ diagnostic_report_current_module (context, diagnostic->location);
pp_set_prefix (context->printer, diagnostic_build_prefix (context,
diagnostic));
}
@@ -459,7 +462,10 @@ diagnostic_report_diagnostic (diagnostic_context *context,
/* FIXME: Stupid search. Optimize later. */
for (i = context->n_classification_history - 1; i >= 0; i --)
{
- if (context->classification_history[i].location <= location)
+ if (linemap_location_before_p
+ (line_table,
+ context->classification_history[i].location,
+ location))
{
if (context->classification_history[i].kind == (int) DK_POP)
{
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 80743549a35..4b1265b7886 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -253,7 +253,7 @@ extern diagnostic_context *global_dc;
/* Diagnostic related functions. */
extern void diagnostic_initialize (diagnostic_context *, int);
extern void diagnostic_finish (diagnostic_context *);
-extern void diagnostic_report_current_module (diagnostic_context *);
+extern void diagnostic_report_current_module (diagnostic_context *, location_t);
/* Force diagnostics controlled by OPTIDX to be kind KIND. */
extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 5212478389d..ef3a0b2f196 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -583,6 +583,37 @@ correct column numbers in warnings or errors, even if tabs appear on the
line. If the value is less than 1 or greater than 100, the option is
ignored. The default is 8.
+@item -fdebug-cpp
+@opindex fdebug-cpp
+This option is only useful for debugging GCC. When used with
+@option{-E}, dumps debugging information about location maps. Every
+token in the output is preceded by the dump of the map its location
+belongs to. The dump of the map holding the location of a token would
+be:
+@quotation
+@{@samp{P}:@file{/file/path};@samp{F}:@file{/includer/path};@samp{L}:@var{line_num};@samp{C}:@var{col_num};@samp{S}:@var{system_header_p};@samp{M}:@var{map_address};@samp{E}:@var{macro_expansion_p},@samp{loc}:@var{location}@}
+@end quotation
+
+When used without @option{-E}, this option has no effect.
+
+@item -ftrack-macro-expansion@r{[}=@var{level}@r{]}
+@opindex ftrack-macro-expansion
+Track locations of tokens across macro expansions. This allows the
+compiler to emit diagnostic about the current macro expansion stack
+when a compilation error occurs in a macro expansion. Using this
+option makes the preprocessor and the compiler consume more
+memory. The @var{level} parameter can be used to choose the level of
+precision of token location tracking thus decreasing the memory
+consumption if necessary. Value @samp{0} of @var{level} de-activates
+this option just as if no @option{-ftrack-macro-expansion} was present
+on the command line. Value @samp{1} tracks tokens locations in a
+degraded mode for the sake of minimal memory overhead. In this mode
+all tokens resulting from the expansion of an argument of a
+function-like macro have the same location. Value @samp{2} tracks
+tokens locations completely. This value is the most memory hungry.
+When this option is given no argument, the default parameter value is
+@samp{2}.
+
@item -fexec-charset=@var{charset}
@opindex fexec-charset
@cindex character set, execution
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 1c688dcf60a..11118edc1d6 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -6584,6 +6584,37 @@ c = a > b; /* The result would be @{0, 0,-1, 0@} */
c = a == b; /* The result would be @{0,-1, 0,-1@} */
@end smallexample
+Vector shuffling is available using functions
+@code{__builtin_shuffle (vec, mask)} and
+@code{__builtin_shuffle (vec0, vec1, mask)}.
+Both functions construct a permutation of elements from one or two
+vectors and return a vector of the same type as the input vector(s).
+The @var{mask} is an integral vector with the same width (@var{W})
+and element count (@var{N}) as the output vector.
+
+The elements of the input vectors are numbered in memory ordering of
+@var{vec0} beginning at 0 and @var{vec1} beginning at @var{N}. The
+elements of @var{mask} are considered modulo @var{N} in the single-operand
+case and modulo @math{2*@var{N}} in the two-operand case.
+
+Consider the following example,
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a = @{1,2,3,4@};
+v4si b = @{5,6,7,8@};
+v4si mask1 = @{0,1,1,3@};
+v4si mask2 = @{0,4,2,5@};
+v4si res;
+
+res = __builtin_shuffle (a, mask1); /* res is @{1,2,2,4@} */
+res = __builtin_shuffle (a, b, mask2); /* res is @{1,5,3,6@} */
+@end smallexample
+
+Note that @code{__builtin_shuffle} is intentionally semantically
+compatible with the OpenCL @code{shuffle} and @code{shuffle2} functions.
+
You can declare variables and use them in function calls and returns, as
well as in assignments and some casts. You can specify a vector type as
a return type for a function. Vector types can also be used as function
@@ -6594,20 +6625,6 @@ to and from other datatypes of the same size).
You cannot operate between vectors of different lengths or different
signedness without a cast.
-A port that supports hardware vector operations, usually provides a set
-of built-in functions that can be used to operate on vectors. For
-example, a function to add two vectors and multiply the result by a
-third could look like this:
-
-@smallexample
-v4si f (v4si a, v4si b, v4si c)
-@{
- v4si tmp = __builtin_addv4si (a, b);
- return __builtin_mulv4si (tmp, c);
-@}
-
-@end smallexample
-
@node Offsetof
@section Offsetof
@findex __builtin_offsetof
@@ -13073,6 +13090,17 @@ long __builtin_vis_fucmple8 (v8qi, v8qi);
long __builtin_vis_fucmpne8 (v8qi, v8qi);
long __builtin_vis_fucmpgt8 (v8qi, v8qi);
long __builtin_vis_fucmpeq8 (v8qi, v8qi);
+
+float __builtin_vis_fhadds (float, float);
+double __builtin_vis_fhaddd (double, double);
+float __builtin_vis_fhsubs (float, float);
+double __builtin_vis_fhsubd (double, double);
+float __builtin_vis_fnhadds (float, float);
+double __builtin_vis_fnhaddd (double, double);
+
+int64_t __builtin_vis_umulxhi (int64_t, int64_t);
+int64_t __builtin_vis_xmulx (int64_t, int64_t);
+int64_t __builtin_vis_xmulxhi (int64_t, int64_t);
@end smallexample
@node SPU Built-in Functions
diff --git a/gcc/doc/fragments.texi b/gcc/doc/fragments.texi
index 28edae98e67..31674f9a5d0 100644
--- a/gcc/doc/fragments.texi
+++ b/gcc/doc/fragments.texi
@@ -1,5 +1,6 @@
@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-@c 1999, 2000, 2001, 2003, 2004, 2005, 2008 Free Software Foundation, Inc.
+@c 1999, 2000, 2001, 2003, 2004, 2005, 2008, 2011
+@c Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -128,12 +129,6 @@ compiler. In that case, set @code{MULTILIB_EXTRA_OPTS} to be the list
of options to be used for all builds. If you set this, you should
probably set @code{CRTSTUFF_T_CFLAGS} to a dash followed by it.
-@findex NATIVE_SYSTEM_HEADER_DIR
-@item NATIVE_SYSTEM_HEADER_DIR
-If the default location for system headers is not @file{/usr/include},
-you must set this to the directory containing the headers. This value
-should match the value of the @code{SYSTEM_INCLUDE_DIR} macro.
-
@findex SPECS
@item SPECS
Unfortunately, setting @code{MULTILIB_EXTRA_OPTS} is not enough, since
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 6dac56d4933..0e76ea6cf43 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -917,16 +917,12 @@ is currently only supported by some targets, notably Linux.
@item --with-native-system-header-dir=@var{dirname}
Specifies that @var{dirname} is the directory that contains native system
-header files, rather than @file{/usr/include}. This option is most useful
+header files, rather than @file{/usr/include}. This option is most useful
if you are creating a compiler that should be isolated from the system
as much as possible. It is most commonly used with the
@option{--with-sysroot} option and will cause GCC to search
@var{dirname} inside the system root specified by that option.
-Please note that for certain targets, such as DJGPP, this value is
-ignored. If the target specifies a default value for native system
-header files then this option is ignored.
-
@item --enable-shared[=@var{package}[,@dots{}]]
Build shared versions of libraries, if shared libraries are supported on
the target platform. Unlike GCC 2.95.x and earlier, shared libraries
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5482ce8c266..c0718ddfe8f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -170,7 +170,7 @@ in the following sections.
@item C Language Options
@xref{C Dialect Options,,Options Controlling C Dialect}.
@gccoptlist{-ansi -std=@var{standard} -fgnu89-inline @gol
--aux-info @var{filename} @gol
+-aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
-fno-asm -fno-builtin -fno-builtin-@var{function} @gol
-fhosted -ffreestanding -fopenmp -fms-extensions -fplan9-extensions @gol
-trigraphs -no-integrated-cpp -traditional -traditional-cpp @gol
@@ -271,7 +271,8 @@ Objective-C and Objective-C++ Dialects}.
-Wunused-label -Wunused-local-typedefs -Wunused-parameter @gol
-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol
-Wunused-but-set-parameter -Wunused-but-set-variable @gol
--Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings}
+-Wvariadic-macros -Wvector-operation-performance -Wvla
+-Wvolatile-register-var -Wwrite-strings}
@item C and Objective-C-only Warning Options
@gccoptlist{-Wbad-function-cast -Wmissing-declarations @gol
@@ -396,10 +397,10 @@ Objective-C and Objective-C++ Dialects}.
-fschedule-insns -fschedule-insns2 -fsection-anchors @gol
-fselective-scheduling -fselective-scheduling2 @gol
-fsel-sched-pipelining -fsel-sched-pipelining-outer-loops @gol
--fsignaling-nans -fsingle-precision-constant -fsplit-ivs-in-unroller @gol
--fsplit-wide-types -fstack-protector -fstack-protector-all @gol
--fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer @gol
--ftree-bit-ccp @gol
+-fshrink-wrap -fsignaling-nans -fsingle-precision-constant @gol
+-fsplit-ivs-in-unroller -fsplit-wide-types -fstack-protector @gol
+-fstack-protector-all -fstrict-aliasing -fstrict-overflow @gol
+-fthread-jumps -ftracer -ftree-bit-ccp @gol
-ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copy-prop @gol
-ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse @gol
-ftree-forwprop -ftree-fre -ftree-loop-if-convert @gol
@@ -428,9 +429,9 @@ Objective-C and Objective-C++ Dialects}.
-iwithprefixbefore @var{dir} -isystem @var{dir} @gol
-imultilib @var{dir} -isysroot @var{dir} @gol
-M -MM -MF -MG -MP -MQ -MT -nostdinc @gol
--P -fworking-directory -remap @gol
--trigraphs -undef -U@var{macro} -Wp,@var{option} @gol
--Xpreprocessor @var{option}}
+-P -fdebug-cpp -ftrack-macro-expansion -fworking-directory @gol
+-remap -trigraphs -undef -U@var{macro} @gol
+-Wp,@var{option} -Xpreprocessor @var{option}}
@item Assembler Option
@xref{Assembler Options,,Passing Options to the Assembler}.
@@ -486,7 +487,7 @@ Objective-C and Objective-C++ Dialects}.
@emph{AVR Options}
@gccoptlist{-mmcu=@var{mcu} -mno-interrupts @gol
--mcall-prologues -mtiny-stack -mint8}
+-mcall-prologues -mtiny-stack -mint8 -mstrict-X}
@emph{Blackfin Options}
@gccoptlist{-mcpu=@var{cpu}@r{[}-@var{sirevision}@r{]} @gol
@@ -605,7 +606,9 @@ Objective-C and Objective-C++ Dialects}.
-mno-wide-multiply -mrtd -malign-double @gol
-mpreferred-stack-boundary=@var{num} @gol
-mincoming-stack-boundary=@var{num} @gol
--mcld -mcx16 -msahf -mmovbe -mcrc32 -mrecip -mvzeroupper @gol
+-mcld -mcx16 -msahf -mmovbe -mcrc32 @gol
+-mrecip -mrecip=@var{opt} @gol
+-mvzeroupper @gol
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
-mavx2 -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma @gol
-msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol
@@ -828,6 +831,7 @@ See RS/6000 and PowerPC Options.
-mrelax@gol
-mmax-constant-size=@gol
-mint-register=@gol
+-mpid@gol
-msave-acc-in-interrupts}
@emph{S/390 and zSeries Options}
@@ -881,7 +885,8 @@ See RS/6000 and PowerPC Options.
-munaligned-doubles -mno-unaligned-doubles @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
--mfmaf -mno-fmaf}
+-mfmaf -mno-fmaf -mpopc -mno-popc @gol
+-mfix-at697f}
@emph{SPU Options}
@gccoptlist{-mwarn-reloc -merror-reloc @gol
@@ -1628,6 +1633,13 @@ character). In the case of function definitions, a K&R-style list of
arguments followed by their declarations is also provided, inside
comments, after the declaration.
+@item -fallow-parameterless-variadic-functions
+Accept variadic functions without named parameters.
+
+Although it is possible to define such a function, this is not very
+useful as it is not possible to read the arguments. This is only
+supported for C as this construct is allowed by C++.
+
@item -fno-asm
@opindex fno-asm
Do not recognize @code{asm}, @code{inline} or @code{typeof} as a
@@ -3187,7 +3199,7 @@ in the case of @code{scanf} formats, this option will suppress the
warning if the unused arguments are all pointers, since the Single
Unix Specification says that such unused arguments are allowed.
-@item -Wno-format-zero-length @r{(C and Objective-C only)}
+@item -Wno-format-zero-length
@opindex Wno-format-zero-length
@opindex Wformat-zero-length
If @option{-Wformat} is specified, do not warn about zero-length formats.
@@ -3220,7 +3232,7 @@ Enable @option{-Wformat} plus format checks not included in
@option{-Wformat}. Currently equivalent to @samp{-Wformat
-Wformat-nonliteral -Wformat-security -Wformat-y2k}.
-@item -Wnonnull @r{(C and Objective-C only)}
+@item -Wnonnull
@opindex Wnonnull
@opindex Wno-nonnull
Warn about passing a null pointer for arguments marked as
@@ -3999,19 +4011,19 @@ The message is in keeping with the output of @option{-fstack-usage}.
If the stack usage is fully static but exceeds the specified amount, it's:
@smallexample
-  warning: stack usage is 1120 bytes
+ warning: stack usage is 1120 bytes
@end smallexample
@item
If the stack usage is (partly) dynamic but bounded, it's:
@smallexample
-  warning: stack usage might be 1648 bytes
+ warning: stack usage might be 1648 bytes
@end smallexample
@item
If the stack usage is (partly) dynamic and not bounded, it's:
@smallexample
-  warning: stack usage might be unbounded
+ warning: stack usage might be unbounded
@end smallexample
@end itemize
@@ -4541,6 +4553,18 @@ Warn if variadic macros are used in pedantic ISO C90 mode, or the GNU
alternate syntax when in pedantic ISO C99 mode. This is default.
To inhibit the warning messages, use @option{-Wno-variadic-macros}.
+@item -Wvector-operation-performance
+@opindex Wvector-operation-performance
+@opindex Wno-vector-operation-performance
+Warn if vector operation is not implemented via SIMD capabilities of the
+architecture. Mainly useful for the performance tuning.
+Vector operation can be implemented @code{piecewise} which means that the
+scalar operation is performed on every vector element;
+@code{in parallel} which means that the vector operation is implemented
+using scalars of wider type, which normally is more performance efficient;
+and @code{as a single scalar} which means that vector fits into a
+scalar type.
+
@item -Wvla
@opindex Wvla
@opindex Wno-vla
@@ -6889,6 +6913,12 @@ This option has no effect until one of @option{-fselective-scheduling} or
When pipelining loops during selective scheduling, also pipeline outer loops.
This option has no effect until @option{-fsel-sched-pipelining} is turned on.
+@item -fshrink-wrap
+@opindex fshrink-wrap
+Emit function prologues only before parts of the function that need it,
+rather than at the top of the function. This flag is enabled by default at
+@option{-O} and higher.
+
@item -fcaller-saves
@opindex fcaller-saves
Enable values to be allocated in registers that will be clobbered by
@@ -9060,8 +9090,7 @@ compile time for more complete debug information. If this is set too
low, value expressions that are available and could be represented in
debug information may end up not being used; setting this higher may
enable the compiler to find more complex debug expressions, but compile
-time may grow exponentially, and even then, it may fail to find more
-usable expressions. The default is 10.
+time and memory use may grow. The default is 12.
@item min-nondebug-insn-uid
Use uids starting at this parameter for nondebug insns. The range below
@@ -10376,10 +10405,16 @@ assembly code. Permissible names are: @samp{arm2}, @samp{arm250},
@samp{fa526}, @samp{fa626},
@samp{fa606te}, @samp{fa626te}, @samp{fmp626}, @samp{fa726te}.
+
@option{-mcpu=generic-@var{arch}} is also permissible, and is
equivalent to @option{-march=@var{arch} -mtune=generic-@var{arch}}.
See @option{-mtune} for more information.
+@option{-mcpu=native} causes the compiler to auto-detect the CPU
+of the build computer. At present, this feature is only supported on
+Linux, and not all architectures are recognised. If the auto-detect is
+unsuccessful the option has no effect.
+
@item -mtune=@var{name}
@opindex mtune
This option is very similar to the @option{-mcpu=} option, except that
@@ -10398,6 +10433,11 @@ processors, balancing between optimizations that benefit some CPUs in the
range, and avoiding performance pitfalls of other CPUs. The effects of
this option may change in future GCC versions as CPU models come and go.
+@option{-mtune=native} causes the compiler to auto-detect the CPU
+of the build computer. At present, this feature is only supported on
+Linux, and not all architectures are recognised. If the auto-detect is
+unsuccessful the option has no effect.
+
@item -march=@var{name}
@opindex march
This specifies the name of the target ARM architecture. GCC uses this
@@ -10411,6 +10451,11 @@ of the @option{-mcpu=} option. Permissible names are: @samp{armv2},
@samp{armv7}, @samp{armv7-a}, @samp{armv7-r}, @samp{armv7-m},
@samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
+@option{-march=native} causes the compiler to auto-detect the architecture
+of the build computer. At present, this feature is only supported on
+Linux, and not all architectures are recognised. If the auto-detect is
+unsuccessful the option has no effect.
+
@item -mfpu=@var{name}
@itemx -mfpe=@var{number}
@itemx -mfp=@var{number}
@@ -10668,6 +10713,23 @@ char will be 1 byte, an int will be 1 byte, a long will be 2 bytes
and long long will be 4 bytes. Please note that this option does not
comply to the C standards, but it will provide you with smaller code
size.
+
+@item -mstrict-X
+@opindex mstrict-X
+Use register @code{X} in a way proposed by the hardware. This means
+that @code{X} will only be used in indirect, post-increment or
+pre-decrement addressing.
+
+Without this option, the @code{X} register may be used in the same way
+as @code{Y} or @code{Z} which then is emulated by additional
+instructions.
+For example, loading a value with @code{X+const} addressing with a
+small @code{const <= 63} to a register @var{Rn} will be printed as
+@example
+adiw r26, const
+ld @var{Rn}, X
+sbiw r26, const
+@end example
@end table
@node Blackfin Options
@@ -12873,6 +12935,22 @@ Note that GCC implements 1.0f/sqrtf(x) in terms of RSQRTSS (or RSQRTPS)
already with @option{-ffast-math} (or the above option combination), and
doesn't need @option{-mrecip}.
+@item -mrecip=@var{opt}
+@opindex mrecip=opt
+This option allows to control which reciprocal estimate instructions
+may be used. @var{opt} is a comma separated list of options, that may
+be preceded by a @code{!} to invert the option:
+@code{all}: enable all estimate instructions,
+@code{default}: enable the default instructions, equivalent to @option{-mrecip},
+@code{none}: disable all estimate instructions, equivalent to @option{-mno-recip},
+@code{div}: enable the approximation for scalar division,
+@code{vec-div}: enable the approximation for vectorized division,
+@code{sqrt}: enable the approximation for scalar square root,
+@code{vec-sqrt}: enable the approximation for vectorized square root.
+
+So for example, @option{-mrecip=all,!sqrt} would enable
+all of the reciprocal approximations, except for square root.
+
@item -mveclibabi=@var{type}
@opindex mveclibabi
Specifies the ABI type to use for vectorizing intrinsics using an
@@ -16579,10 +16657,11 @@ which can be placed into the small data area. Using the small data
area can lead to smaller and faster code, but the size of area is
limited and it is up to the programmer to ensure that the area does
not overflow. Also when the small data area is used one of the RX's
-registers (@code{r13}) is reserved for use pointing to this area, so
-it is no longer available for use by the compiler. This could result
-in slower and/or larger code if variables which once could have been
-held in @code{r13} are now pushed onto the stack.
+registers (usually @code{r13}) is reserved for use pointing to this
+area, so it is no longer available for use by the compiler. This
+could result in slower and/or larger code if variables which once
+could have been held in the reserved register are now pushed onto the
+stack.
Note, common variables (variables which have not been initialised) and
constants are not placed into the small data area as they are assigned
@@ -16591,9 +16670,10 @@ to other sections in the output executable.
The default value is zero, which disables this feature. Note, this
feature is not enabled by default with higher optimization levels
(@option{-O2} etc) because of the potentially detrimental effects of
-reserving register @code{r13}. It is up to the programmer to
-experiment and discover whether this feature is of benefit to their
-program.
+reserving a register. It is up to the programmer to experiment and
+discover whether this feature is of benefit to their program. See the
+description of the @option{-mpid} option for a description of how the
+actual register to hold the small data area pointer is chosen.
@item -msim
@itemx -mno-sim
@@ -16648,6 +16728,35 @@ the accumulator register, for example because it performs 64-bit
multiplications. The default is to ignore the accumulator as this
makes the interrupt handlers faster.
+@item -mpid
+@itemx -mno-pid
+@opindex mpid
+@opindex mno-pid
+Enables the generation of position independent data. When enabled any
+access to constant data will done via an offset from a base address
+held in a register. This allows the location of constant data to be
+determined at run-time without requiring the executable to be
+relocated, which is a benefit to embedded applications with tight
+memory constraints. Data that can be modified is not affected by this
+option.
+
+Note, using this feature reserves a register, usually @code{r13}, for
+the constant data base address. This can result in slower and/or
+larger code, especially in complicated functions.
+
+The actual register chosen to hold the constant data base address
+depends upon whether the @option{-msmall-data-limit} and/or the
+@option{-mint-register} command line options are enabled. Starting
+with register @code{r13} and proceeding downwards, registers are
+allocated first to satisfy the requirements of @option{-mint-register},
+then @option{-mpid} and finally @option{-msmall-data-limit}. Thus it
+is possible for the small data area register to be @code{r8} if both
+@option{-mint-register=4} and @option{-mpid} are specified on the
+command line.
+
+By default this feature is not enabled. The default can be restored
+via the @option{-mno-pid} command line option.
+
@end table
@emph{Note:} The generic GCC command line @option{-ffixed-@var{reg}}
@@ -17354,7 +17463,7 @@ for machine type @var{cpu_type}. Supported values for @var{cpu_type} are
@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3},
and @samp{niagara4}.
-Native Solaris and Linux toolchains also support the value @samp{native},
+Native Solaris and GNU/Linux toolchains also support the value @samp{native},
which selects the best architecture option for the host processor.
@option{-mcpu=native} has no effect if GCC does not recognize
the processor.
@@ -17427,7 +17536,7 @@ that select a particular CPU implementation. Those are @samp{cypress},
@samp{supersparc}, @samp{hypersparc}, @samp{leon}, @samp{f930}, @samp{f934},
@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc}, @samp{ultrasparc3},
@samp{niagara}, @samp{niagara2}, @samp{niagara3} and @samp{niagara4}. With
-native Solaris and Linux toolchains, @samp{native} can also be used.
+native Solaris and GNU/Linux toolchains, @samp{native} can also be used.
@item -mv8plus
@itemx -mno-v8plus
@@ -17465,6 +17574,15 @@ default is @option{-mvis3} when targetting a cpu that supports such
instructions, such as niagara-3 and later. Setting @option{-mvis3}
also sets @option{-mvis2} and @option{-mvis}.
+@item -mpopc
+@itemx -mno-popc
+@opindex mpopc
+@opindex mno-popc
+With @option{-mpopc}, GCC generates code that takes advantage of the UltraSPARC
+population count instruction. The default is @option{-mpopc}
+when targetting a cpu that supports such instructions, such as Niagara-2 and
+later.
+
@item -mfmaf
@itemx -mno-fmaf
@opindex mfmaf
@@ -17473,6 +17591,11 @@ With @option{-mfmaf}, GCC generates code that takes advantage of the UltraSPARC
Fused Multiply-Add Floating-point extensions. The default is @option{-mfmaf}
when targetting a cpu that supports such instructions, such as Niagara-3 and
later.
+
+@item -mfix-at697f
+@opindex mfix-at697f
+Enable the documented workaround for the single erratum of the Atmel AT697F
+processor (which corresponds to erratum #13 of the AT697E processor).
@end table
These @samp{-m} options are supported in addition to the above
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 1aa8552c5d4..4a0bcfa1bf1 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -4028,6 +4028,40 @@ will be set to the value @var{op1} & @var{msk} | @var{op2} & ~@var{msk}
where @var{msk} is computed by element-wise evaluation of the vector
comparison with a truth value of all-ones and a false value of all-zeros.
+@cindex @code{vec_perm@var{m}} instruction pattern
+@item @samp{vec_perm@var{m}}
+Output a (variable) vector permutation. Operand 0 is the destination
+to receive elements from operand 1 and operand 2, which are of mode
+@var{m}. Operand 3 is the @dfn{selector}. It is an integral mode
+vector of the same width and number of elements as mode @var{m}.
+
+The input elements are numbered from 0 in operand 1 through
+@math{2*@var{N}-1} in operand 2. The elements of the selector must
+be computed modulo @math{2*@var{N}}. Note that if
+@code{rtx_equal_p(operand1, operand2)}, this can be implemented
+with just operand 1 and selector elements modulo @var{N}.
+
+In order to make things easy for a number of targets, if there is no
+@samp{vec_perm} pattern for mode @var{m}, but there is for mode @var{q}
+where @var{q} is a vector of @code{QImode} of the same width as @var{m},
+the middle-end will lower the mode @var{m} @code{VEC_PERM_EXPR} to
+mode @var{q}.
+
+@cindex @code{vec_perm_const@var{m}} instruction pattern
+@item @samp{vec_perm_const@var{m}}
+Like @samp{vec_perm} except that the permutation is a compile-time
+constant. That is, operand 3, the @dfn{selector}, is a @code{CONST_VECTOR}.
+
+Some targets cannot perform a permutation with a variable selector,
+but can efficiently perform a constant permutation. Further, the
+target hook @code{vec_perm_ok} is queried to determine if the
+specific constant permutation is available efficiently; the named
+pattern is never expanded without @code{vec_perm_ok} returning true.
+
+There is no need for a target to supply both @samp{vec_perm@var{m}}
+and @samp{vec_perm_const@var{m}} if the former can trivially implement
+the operation with, say, the vector constant loaded into a register.
+
@cindex @code{push@var{m}1} instruction pattern
@item @samp{push@var{m}1}
Output a push instruction. Operand 0 is value to push. Used only when
@@ -4238,6 +4272,17 @@ are vectors with N signed/unsigned elements of size S@. Multiply the high/low
elements of the two vectors, and put the N/2 products of size 2*S in the
output vector (operand 0).
+@cindex @code{vec_widen_ushiftl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_ushiftl_lo_@var{m}} instruction pattern
+@cindex @code{vec_widen_sshiftl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_sshiftl_lo_@var{m}} instruction pattern
+@item @samp{vec_widen_ushiftl_hi_@var{m}}, @samp{vec_widen_ushiftl_lo_@var{m}}
+@itemx @samp{vec_widen_sshiftl_hi_@var{m}}, @samp{vec_widen_sshiftl_lo_@var{m}}
+Signed/Unsigned widening shift left. The first input (operand 1) is a vector
+with N signed/unsigned elements of size S@. Operand 2 is a constant. Shift
+the high/low elements of operand 1, and put the N/2 results of size 2*S in the
+output vector (operand 0).
+
@cindex @code{mulhisi3} instruction pattern
@item @samp{mulhisi3}
Multiply operands 1 and 2, which have mode @code{HImode}, and store
diff --git a/gcc/doc/objc.texi b/gcc/doc/objc.texi
index dd04eda82f7..a36b0e70530 100644
--- a/gcc/doc/objc.texi
+++ b/gcc/doc/objc.texi
@@ -635,7 +635,8 @@ following class does this:
+ (void)initialize
@{
- class_ivar_set_gcinvisible (self, "weakPointer", YES);
+ if (self == objc_lookUpClass ("WeakPointer"))
+ class_ivar_set_gcinvisible (self, "weakPointer", YES);
@}
- initWithPointer:(const void*)p
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 7143f0f1c92..f9e4260b238 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -470,33 +470,15 @@ initialize the necessary environment variables.
Define this macro as a C string constant if you wish to override the
standard choice of @file{/usr/local/include} as the default prefix to
try when searching for local header files. @code{LOCAL_INCLUDE_DIR}
-comes before @code{SYSTEM_INCLUDE_DIR} in the search order.
+comes before @code{NATIVE_SYSTEM_HEADER_DIR} (set in
+@file{config.gcc}, normally @file{/usr/include}) in the search order.
Cross compilers do not search either @file{/usr/local/include} or its
replacement.
@end defmac
-@defmac SYSTEM_INCLUDE_DIR
-Define this macro as a C string constant if you wish to specify a
-system-specific directory to search for header files before the standard
-directory. @code{SYSTEM_INCLUDE_DIR} comes before
-@code{STANDARD_INCLUDE_DIR} in the search order.
-
-Cross compilers do not use this macro and do not search the directory
-specified.
-@end defmac
-
-@defmac STANDARD_INCLUDE_DIR
-Define this macro as a C string constant if you wish to override the
-standard choice of @file{/usr/include} as the default prefix to
-try when searching for header files.
-
-Cross compilers ignore this macro and do not search either
-@file{/usr/include} or its replacement.
-@end defmac
-
-@defmac STANDARD_INCLUDE_COMPONENT
-The ``component'' corresponding to @code{STANDARD_INCLUDE_DIR}.
+@defmac NATIVE_SYSTEM_HEADER_COMPONENT
+The ``component'' corresponding to @code{NATIVE_SYSTEM_HEADER_DIR}.
See @code{INCLUDE_DEFAULTS}, below, for the description of components.
If you do not define this macro, no component is used.
@end defmac
@@ -505,8 +487,8 @@ If you do not define this macro, no component is used.
Define this macro if you wish to override the entire default search path
for include files. For a native compiler, the default search path
usually consists of @code{GCC_INCLUDE_DIR}, @code{LOCAL_INCLUDE_DIR},
-@code{SYSTEM_INCLUDE_DIR}, @code{GPLUSPLUS_INCLUDE_DIR}, and
-@code{STANDARD_INCLUDE_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
+@code{GPLUSPLUS_INCLUDE_DIR}, and
+@code{NATIVE_SYSTEM_HEADER_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
and @code{GCC_INCLUDE_DIR} are defined automatically by @file{Makefile},
and specify private search areas for GCC@. The directory
@code{GPLUSPLUS_INCLUDE_DIR} is used only for C++ programs.
@@ -7530,18 +7512,6 @@ itself, by calling, for example, @code{output_operand_lossage}, it may just
return @code{true}.
@end deftypefn
-@defmac OUTPUT_ADDR_CONST_EXTRA (@var{stream}, @var{x}, @var{fail})
-A C statement to recognize @var{rtx} patterns that
-@code{output_addr_const} can't deal with, and output assembly code to
-@var{stream} corresponding to the pattern @var{x}. This may be used to
-allow machine-dependent @code{UNSPEC}s to appear within constants.
-
-If @code{OUTPUT_ADDR_CONST_EXTRA} fails to recognize a pattern, it must
-@code{goto fail}, so that a standard error message is printed. If it
-prints an error message itself, by calling, for example,
-@code{output_operand_lossage}, it may just complete normally.
-@end defmac
-
@defmac ASM_OUTPUT_ASCII (@var{stream}, @var{ptr}, @var{len})
A C statement to output to the stdio stream @var{stream} an assembler
instruction to assemble a string constant containing the @var{len}
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 67838269dff..e7e25888e37 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -468,33 +468,15 @@ initialize the necessary environment variables.
Define this macro as a C string constant if you wish to override the
standard choice of @file{/usr/local/include} as the default prefix to
try when searching for local header files. @code{LOCAL_INCLUDE_DIR}
-comes before @code{SYSTEM_INCLUDE_DIR} in the search order.
+comes before @code{NATIVE_SYSTEM_HEADER_DIR} (set in
+@file{config.gcc}, normally @file{/usr/include}) in the search order.
Cross compilers do not search either @file{/usr/local/include} or its
replacement.
@end defmac
-@defmac SYSTEM_INCLUDE_DIR
-Define this macro as a C string constant if you wish to specify a
-system-specific directory to search for header files before the standard
-directory. @code{SYSTEM_INCLUDE_DIR} comes before
-@code{STANDARD_INCLUDE_DIR} in the search order.
-
-Cross compilers do not use this macro and do not search the directory
-specified.
-@end defmac
-
-@defmac STANDARD_INCLUDE_DIR
-Define this macro as a C string constant if you wish to override the
-standard choice of @file{/usr/include} as the default prefix to
-try when searching for header files.
-
-Cross compilers ignore this macro and do not search either
-@file{/usr/include} or its replacement.
-@end defmac
-
-@defmac STANDARD_INCLUDE_COMPONENT
-The ``component'' corresponding to @code{STANDARD_INCLUDE_DIR}.
+@defmac NATIVE_SYSTEM_HEADER_COMPONENT
+The ``component'' corresponding to @code{NATIVE_SYSTEM_HEADER_DIR}.
See @code{INCLUDE_DEFAULTS}, below, for the description of components.
If you do not define this macro, no component is used.
@end defmac
@@ -503,8 +485,8 @@ If you do not define this macro, no component is used.
Define this macro if you wish to override the entire default search path
for include files. For a native compiler, the default search path
usually consists of @code{GCC_INCLUDE_DIR}, @code{LOCAL_INCLUDE_DIR},
-@code{SYSTEM_INCLUDE_DIR}, @code{GPLUSPLUS_INCLUDE_DIR}, and
-@code{STANDARD_INCLUDE_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
+@code{GPLUSPLUS_INCLUDE_DIR}, and
+@code{NATIVE_SYSTEM_HEADER_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
and @code{GCC_INCLUDE_DIR} are defined automatically by @file{Makefile},
and specify private search areas for GCC@. The directory
@code{GPLUSPLUS_INCLUDE_DIR} is used only for C++ programs.
@@ -7446,18 +7428,6 @@ itself, by calling, for example, @code{output_operand_lossage}, it may just
return @code{true}.
@end deftypefn
-@defmac OUTPUT_ADDR_CONST_EXTRA (@var{stream}, @var{x}, @var{fail})
-A C statement to recognize @var{rtx} patterns that
-@code{output_addr_const} can't deal with, and output assembly code to
-@var{stream} corresponding to the pattern @var{x}. This may be used to
-allow machine-dependent @code{UNSPEC}s to appear within constants.
-
-If @code{OUTPUT_ADDR_CONST_EXTRA} fails to recognize a pattern, it must
-@code{goto fail}, so that a standard error message is printed. If it
-prints an error message itself, by calling, for example,
-@code{output_operand_lossage}, it may just complete normally.
-@end defmac
-
@defmac ASM_OUTPUT_ASCII (@var{stream}, @var{ptr}, @var{len})
A C statement to output to the stdio stream @var{stream} an assembler
instruction to assemble a string constant containing the @var{len}
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c11f666bfbf..e328201a82a 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -12502,7 +12502,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
legitimate to make the Dwarf info refer to the whole register which
contains the given subreg. */
if (REG_P (SUBREG_REG (rtl)) && subreg_lowpart_p (rtl))
- loc_result = loc_descriptor (SUBREG_REG (rtl), mode, initialized);
+ loc_result = loc_descriptor (SUBREG_REG (rtl),
+ GET_MODE (SUBREG_REG (rtl)), initialized);
else
goto do_default;
break;
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index dae7669297a..8465237da60 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1696,6 +1696,12 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
&& !TREE_THIS_VOLATILE (base))
MEM_READONLY_P (ref) = 1;
+ /* Mark static const strings readonly as well. */
+ if (base && TREE_CODE (base) == STRING_CST
+ && TREE_READONLY (base)
+ && TREE_STATIC (base))
+ MEM_READONLY_P (ref) = 1;
+
/* If this expression uses it's parent's alias set, mark it such
that we won't change it. */
if (component_uses_parent_alias_set (t))
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 1528fbb1112..b3e6d6d1816 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -3467,7 +3467,7 @@ expand_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1,
/* Try widening multiplication. */
moptab = unsignedp ? umul_widen_optab : smul_widen_optab;
- if (optab_handler (moptab, wider_mode) != CODE_FOR_nothing
+ if (widening_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing
&& mul_widen_cost[speed][wider_mode] < max_cost)
{
tem = expand_binop (wider_mode, moptab, op0, narrow_op1, 0,
@@ -3504,7 +3504,7 @@ expand_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1,
/* Try widening multiplication of opposite signedness, and adjust. */
moptab = unsignedp ? smul_widen_optab : umul_widen_optab;
- if (optab_handler (moptab, wider_mode) != CODE_FOR_nothing
+ if (widening_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing
&& size - 1 < BITS_PER_WORD
&& (mul_widen_cost[speed][wider_mode] + 2 * shift_cost[speed][mode][size-1]
+ 4 * add_cost[speed][mode] < max_cost))
diff --git a/gcc/expr.c b/gcc/expr.c
index 97edd460019..a4cfee005d0 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2180,6 +2180,112 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
return tgtblk;
}
+/* Copy BLKmode value SRC into a register of mode MODE. Return the
+ register if it contains any data, otherwise return null.
+
+ This is used on targets that return BLKmode values in registers. */
+
+rtx
+copy_blkmode_to_reg (enum machine_mode mode, tree src)
+{
+ int i, n_regs;
+ unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0, bytes;
+ unsigned int bitsize;
+ rtx *dst_words, dst, x, src_word = NULL_RTX, dst_word = NULL_RTX;
+ enum machine_mode dst_mode;
+
+ gcc_assert (TYPE_MODE (TREE_TYPE (src)) == BLKmode);
+
+ x = expand_normal (src);
+
+ bytes = int_size_in_bytes (TREE_TYPE (src));
+ if (bytes == 0)
+ return NULL_RTX;
+
+ /* If the structure doesn't take up a whole number of words, see
+ whether the register value should be padded on the left or on
+ the right. Set PADDING_CORRECTION to the number of padding
+ bits needed on the left side.
+
+ In most ABIs, the structure will be returned at the least end of
+ the register, which translates to right padding on little-endian
+ targets and left padding on big-endian targets. The opposite
+ holds if the structure is returned at the most significant
+ end of the register. */
+ if (bytes % UNITS_PER_WORD != 0
+ && (targetm.calls.return_in_msb (TREE_TYPE (src))
+ ? !BYTES_BIG_ENDIAN
+ : BYTES_BIG_ENDIAN))
+ padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
+ * BITS_PER_UNIT));
+
+ n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ dst_words = XALLOCAVEC (rtx, n_regs);
+ bitsize = MIN (TYPE_ALIGN (TREE_TYPE (src)), BITS_PER_WORD);
+
+ /* Copy the structure BITSIZE bits at a time. */
+ for (bitpos = 0, xbitpos = padding_correction;
+ bitpos < bytes * BITS_PER_UNIT;
+ bitpos += bitsize, xbitpos += bitsize)
+ {
+ /* We need a new destination pseudo each time xbitpos is
+ on a word boundary and when xbitpos == padding_correction
+ (the first time through). */
+ if (xbitpos % BITS_PER_WORD == 0
+ || xbitpos == padding_correction)
+ {
+ /* Generate an appropriate register. */
+ dst_word = gen_reg_rtx (word_mode);
+ dst_words[xbitpos / BITS_PER_WORD] = dst_word;
+
+ /* Clear the destination before we move anything into it. */
+ emit_move_insn (dst_word, CONST0_RTX (word_mode));
+ }
+
+ /* We need a new source operand each time bitpos is on a word
+ boundary. */
+ if (bitpos % BITS_PER_WORD == 0)
+ src_word = operand_subword_force (x, bitpos / BITS_PER_WORD, BLKmode);
+
+ /* Use bitpos for the source extraction (left justified) and
+ xbitpos for the destination store (right justified). */
+ store_bit_field (dst_word, bitsize, xbitpos % BITS_PER_WORD,
+ 0, 0, word_mode,
+ extract_bit_field (src_word, bitsize,
+ bitpos % BITS_PER_WORD, 1, false,
+ NULL_RTX, word_mode, word_mode));
+ }
+
+ if (mode == BLKmode)
+ {
+ /* Find the smallest integer mode large enough to hold the
+ entire structure. */
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ /* Have we found a large enough mode? */
+ if (GET_MODE_SIZE (mode) >= bytes)
+ break;
+
+ /* A suitable mode should have been found. */
+ gcc_assert (mode != VOIDmode);
+ }
+
+ if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode))
+ dst_mode = word_mode;
+ else
+ dst_mode = mode;
+ dst = gen_reg_rtx (dst_mode);
+
+ for (i = 0; i < n_regs; i++)
+ emit_move_insn (operand_subword (dst, i, 0, dst_mode), dst_words[i]);
+
+ if (mode != dst_mode)
+ dst = gen_lowpart (mode, dst);
+
+ return dst;
+}
+
/* Add a USE expression for REG to the (possibly empty) list pointed
to by CALL_FUSAGE. REG must denote a hard register. */
@@ -4438,6 +4544,27 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
}
}
+/* Return the alignment of the object EXP, also considering its type
+ when we do not know of explicit misalignment.
+ ??? Note that, in the general case, the type of an expression is not kept
+ consistent with misalignment information by the front-end, for
+ example when taking the address of a member of a packed structure.
+ However, in most of the cases, expressions have the alignment of
+ their type, so we optimistically fall back to the alignment of the
+ type when we cannot compute a misalignment. */
+
+static unsigned int
+get_object_or_type_alignment (tree exp)
+{
+ unsigned HOST_WIDE_INT misalign;
+ unsigned int align = get_object_alignment_1 (exp, &misalign);
+ if (misalign != 0)
+ align = (misalign & -misalign);
+ else
+ align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
+ return align;
+}
+
/* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL
is true, try generating a nontemporal store. */
@@ -4447,7 +4574,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
rtx to_rtx = 0;
rtx result;
enum machine_mode mode;
- int align;
+ unsigned int align;
enum insn_code icode;
/* Don't crash if the lhs of the assignment was erroneous. */
@@ -4465,8 +4592,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
if ((TREE_CODE (to) == MEM_REF
|| TREE_CODE (to) == TARGET_MEM_REF)
&& mode != BLKmode
- && ((align = MAX (TYPE_ALIGN (TREE_TYPE (to)), get_object_alignment (to)))
- < (signed) GET_MODE_ALIGNMENT (mode))
+ && ((align = get_object_or_type_alignment (to))
+ < GET_MODE_ALIGNMENT (mode))
&& ((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing))
{
@@ -4720,7 +4847,9 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from)
&& COMPLETE_TYPE_P (TREE_TYPE (from))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
- && ! (((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
+ && ! (((TREE_CODE (to) == VAR_DECL
+ || TREE_CODE (to) == PARM_DECL
+ || TREE_CODE (to) == RESULT_DECL)
&& REG_P (DECL_RTL (to)))
|| TREE_CODE (to) == SSA_NAME))
{
@@ -4766,12 +4895,15 @@ expand_assignment (tree to, tree from, bool nontemporal)
rtx temp;
push_temp_slots ();
- temp = expand_expr (from, NULL_RTX, GET_MODE (to_rtx), EXPAND_NORMAL);
+ if (REG_P (to_rtx) && TYPE_MODE (TREE_TYPE (from)) == BLKmode)
+ temp = copy_blkmode_to_reg (GET_MODE (to_rtx), from);
+ else
+ temp = expand_expr (from, NULL_RTX, GET_MODE (to_rtx), EXPAND_NORMAL);
if (GET_CODE (to_rtx) == PARALLEL)
emit_group_load (to_rtx, temp, TREE_TYPE (from),
int_size_in_bytes (TREE_TYPE (from)));
- else
+ else if (temp)
emit_move_insn (to_rtx, temp);
preserve_temp_slots (to_rtx);
@@ -8600,12 +8732,30 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
return target;
}
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ {
+ tree oprnd0 = treeop0;
+ tree oprnd1 = treeop1;
+
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
+ target, unsignedp);
+ gcc_assert (target);
+ return target;
+ }
+
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
mode = TYPE_MODE (TREE_TYPE (treeop0));
goto binop;
+ case VEC_PERM_EXPR:
+ target = expand_vec_perm_expr (type, treeop0, treeop1, treeop2, target);
+ gcc_assert (target);
+ return target;
+
case DOT_PROD_EXPR:
{
tree oprnd0 = treeop0;
@@ -8950,10 +9100,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return temp;
}
- /* If the mode of DECL_RTL does not match that of the decl, it
- must be a promoted value. We return a SUBREG of the wanted mode,
- but mark it so that we know that it was already extended. */
- if (REG_P (decl_rtl) && GET_MODE (decl_rtl) != DECL_MODE (exp))
+ /* If the mode of DECL_RTL does not match that of the decl,
+ there are two cases: we are dealing with a BLKmode value
+ that is returned in a register, or we are dealing with
+ a promoted value. In the latter case, return a SUBREG
+ of the wanted mode, but mark it so that we know that it
+ was already extended. */
+ if (REG_P (decl_rtl)
+ && DECL_MODE (exp) != BLKmode
+ && GET_MODE (decl_rtl) != DECL_MODE (exp))
{
enum machine_mode pmode;
@@ -9120,7 +9275,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
struct mem_address addr;
enum insn_code icode;
- int align;
+ unsigned int align;
get_address_description (exp, &addr);
op0 = addr_for_mem_ref (&addr, as, true);
@@ -9128,9 +9283,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
set_mem_addr_space (temp, as);
- align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+ align = get_object_or_type_alignment (exp);
if (mode != BLKmode
- && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+ && align < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
&& ((icode = optab_handler (movmisalign_optab, mode))
@@ -9157,7 +9312,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
tree base = TREE_OPERAND (exp, 0);
gimple def_stmt;
enum insn_code icode;
- int align;
+ unsigned align;
/* Handle expansion of non-aliased memory with non-BLKmode. That
might end up in a register. */
if (TREE_CODE (base) == ADDR_EXPR)
@@ -9208,7 +9363,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
gimple_assign_rhs1 (def_stmt), mask);
TREE_OPERAND (exp, 0) = base;
}
- align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+ align = get_object_or_type_alignment (exp);
op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address_addr_space (address_mode, op0, as);
if (!integer_zerop (TREE_OPERAND (exp, 1)))
@@ -9224,7 +9379,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (TREE_THIS_VOLATILE (exp))
MEM_VOLATILE_P (temp) = 1;
if (mode != BLKmode
- && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+ && align < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
&& ((icode = optab_handler (movmisalign_optab, mode))
@@ -10308,6 +10463,17 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
+
+ /* For vector typed comparisons emit code to generate the desired
+ all-ones or all-zeros mask. Conveniently use the VEC_COND_EXPR
+ expander for this. */
+ if (TREE_CODE (ops->type) == VECTOR_TYPE)
+ {
+ tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
+ tree if_true = constant_boolean_node (true, ops->type);
+ tree if_false = constant_boolean_node (false, ops->type);
+ return expand_vec_cond_expr (ops->type, ifexp, if_true, if_false, target);
+ }
/* For vector typed comparisons emit code to generate the desired
all-ones or all-zeros mask. Conveniently use the VEC_COND_EXPR
diff --git a/gcc/expr.h b/gcc/expr.h
index 16521866bfe..1bf1369ac96 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -325,6 +325,8 @@ extern rtx copy_blkmode_from_reg (rtx, rtx, tree);
Mode is TYPE_MODE of the non-promoted parameter, or VOIDmode. */
extern void use_reg_mode (rtx *, rtx, enum machine_mode);
+extern rtx copy_blkmode_to_reg (enum machine_mode, tree);
+
/* Mark REG as holding a parameter for the next CALL_INSN. */
static inline void
use_reg (rtx *fusage, rtx reg)
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 79ebd8b5701..dc14576c1ad 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -112,13 +112,13 @@ static tree decode_field_reference (location_t, tree, HOST_WIDE_INT *,
static int all_ones_mask_p (const_tree, int);
static tree sign_bit_p (tree, const_tree);
static int simple_operand_p (const_tree);
+static bool simple_operand_p_2 (tree);
static tree range_binop (enum tree_code, tree, tree, int, tree, int);
static tree range_predecessor (tree);
static tree range_successor (tree);
static tree fold_range_test (location_t, enum tree_code, tree, tree, tree);
static tree fold_cond_expr_with_comparison (location_t, tree, tree, tree, tree);
static tree unextend (tree, int, int, tree);
-static tree fold_truthop (location_t, enum tree_code, tree, tree, tree);
static tree optimize_minmax_comparison (location_t, enum tree_code,
tree, tree, tree);
static tree extract_muldiv (tree, tree, enum tree_code, tree, bool *);
@@ -3500,7 +3500,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
return lhs;
}
-/* Subroutine for fold_truthop: decode a field reference.
+/* Subroutine for fold_truth_andor_1: decode a field reference.
If EXP is a comparison reference, we return the innermost reference.
@@ -3668,7 +3668,7 @@ sign_bit_p (tree exp, const_tree val)
return NULL_TREE;
}
-/* Subroutine for fold_truthop: determine if an operand is simple enough
+/* Subroutine for fold_truth_andor_1: determine if an operand is simple enough
to be evaluated unconditionally. */
static int
@@ -3678,7 +3678,7 @@ simple_operand_p (const_tree exp)
STRIP_NOPS (exp);
return (CONSTANT_CLASS_P (exp)
- || TREE_CODE (exp) == SSA_NAME
+ || TREE_CODE (exp) == SSA_NAME
|| (DECL_P (exp)
&& ! TREE_ADDRESSABLE (exp)
&& ! TREE_THIS_VOLATILE (exp)
@@ -3692,6 +3692,36 @@ simple_operand_p (const_tree exp)
registers aren't expensive. */
&& (! TREE_STATIC (exp) || DECL_REGISTER (exp))));
}
+
+/* Subroutine for fold_truth_andor: determine if an operand is simple enough
+ to be evaluated unconditionally.
+ I addition to simple_operand_p, we assume that comparisons and logic-not
+ operations are simple, if their operands are simple, too. */
+
+static bool
+simple_operand_p_2 (tree exp)
+{
+ enum tree_code code;
+
+ /* Strip any conversions that don't change the machine mode. */
+ STRIP_NOPS (exp);
+
+ code = TREE_CODE (exp);
+
+ if (TREE_SIDE_EFFECTS (exp)
+ || tree_could_trap_p (exp))
+ return false;
+
+ if (TREE_CODE_CLASS (code) == tcc_comparison)
+ return (simple_operand_p (TREE_OPERAND (exp, 0))
+ && simple_operand_p (TREE_OPERAND (exp, 1)));
+
+ if (code == TRUTH_NOT_EXPR)
+ return simple_operand_p_2 (TREE_OPERAND (exp, 0));
+
+ return simple_operand_p (exp);
+}
+
/* The following functions are subroutines to fold_range_test and allow it to
try to change a logical combination of comparisons into a range test.
@@ -4888,7 +4918,7 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
return 0;
}
-/* Subroutine for fold_truthop: C is an INTEGER_CST interpreted as a P
+/* Subroutine for fold_truth_andor_1: C is an INTEGER_CST interpreted as a P
bit value. Arrange things so the extra bits will be set to zero if and
only if C is signed-extended to its full width. If MASK is nonzero,
it is an INTEGER_CST that should be AND'ed with the extra bits. */
@@ -5025,8 +5055,8 @@ merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop,
We return the simplified tree or 0 if no optimization is possible. */
static tree
-fold_truthop (location_t loc, enum tree_code code, tree truth_type,
- tree lhs, tree rhs)
+fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
+ tree lhs, tree rhs)
{
/* If this is the "or" of two comparisons, we can do something if
the comparisons are NE_EXPR. If this is the "and", we can do something
@@ -5054,8 +5084,6 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
tree lntype, rntype, result;
HOST_WIDE_INT first_bit, end_bit;
int volatilep;
- tree orig_lhs = lhs, orig_rhs = rhs;
- enum tree_code orig_code = code;
/* Start by getting the comparison codes. Fail if anything is volatile.
If one operand is a BIT_AND_EXPR with the constant one, treat it as if
@@ -5119,8 +5147,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
/* If the RHS can be evaluated unconditionally and its operands are
simple, it wins to evaluate the RHS unconditionally on machines
with expensive branches. In this case, this isn't a comparison
- that can be merged. Avoid doing this if the RHS is a floating-point
- comparison since those can trap. */
+ that can be merged. */
if (BRANCH_COST (optimize_function_for_speed_p (cfun),
false) >= 2
@@ -5149,13 +5176,6 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
ll_arg, rl_arg),
build_int_cst (TREE_TYPE (ll_arg), 0));
-
- if (LOGICAL_OP_NON_SHORT_CIRCUIT)
- {
- if (code != orig_code || lhs != orig_lhs || rhs != orig_rhs)
- return build2_loc (loc, code, truth_type, lhs, rhs);
- return NULL_TREE;
- }
}
/* See if the comparisons can be merged. Then get all the parameters for
@@ -7946,6 +7966,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
that this happens when X or Y is NOP_EXPR or Y is INTEGER_CST. */
if (POINTER_TYPE_P (type)
&& TREE_CODE (arg0) == POINTER_PLUS_EXPR
+ && (!TYPE_RESTRICT (type) || TYPE_RESTRICT (TREE_TYPE (arg0)))
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
|| TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
|| TREE_CODE (TREE_OPERAND (arg0, 1)) == NOP_EXPR))
@@ -8379,13 +8400,69 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type,
lhs is another similar operation, try to merge its rhs with our
rhs. Then try to merge our lhs and rhs. */
if (TREE_CODE (arg0) == code
- && 0 != (tem = fold_truthop (loc, code, type,
- TREE_OPERAND (arg0, 1), arg1)))
+ && 0 != (tem = fold_truth_andor_1 (loc, code, type,
+ TREE_OPERAND (arg0, 1), arg1)))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
- if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
+ if ((tem = fold_truth_andor_1 (loc, code, type, arg0, arg1)) != 0)
return tem;
+ if ((BRANCH_COST (optimize_function_for_speed_p (cfun),
+ false) >= 2)
+ && LOGICAL_OP_NON_SHORT_CIRCUIT
+ && (code == TRUTH_AND_EXPR
+ || code == TRUTH_ANDIF_EXPR
+ || code == TRUTH_OR_EXPR
+ || code == TRUTH_ORIF_EXPR))
+ {
+ enum tree_code ncode, icode;
+
+ ncode = (code == TRUTH_ANDIF_EXPR || code == TRUTH_AND_EXPR)
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR;
+ icode = ncode == TRUTH_AND_EXPR ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
+
+ /* Transform ((A AND-IF B) AND[-IF] C) into (A AND-IF (B AND C)),
+ or ((A OR-IF B) OR[-IF] C) into (A OR-IF (B OR C))
+ We don't want to pack more than two leafs to a non-IF AND/OR
+ expression.
+ If tree-code of left-hand operand isn't an AND/OR-IF code and not
+ equal to IF-CODE, then we don't want to add right-hand operand.
+ If the inner right-hand side of left-hand operand has
+ side-effects, or isn't simple, then we can't add to it,
+ as otherwise we might destroy if-sequence. */
+ if (TREE_CODE (arg0) == icode
+ && simple_operand_p_2 (arg1)
+ /* Needed for sequence points to handle trappings, and
+ side-effects. */
+ && simple_operand_p_2 (TREE_OPERAND (arg0, 1)))
+ {
+ tem = fold_build2_loc (loc, ncode, type, TREE_OPERAND (arg0, 1),
+ arg1);
+ return fold_build2_loc (loc, icode, type, TREE_OPERAND (arg0, 0),
+ tem);
+ }
+ /* Same as abouve but for (A AND[-IF] (B AND-IF C)) -> ((A AND B) AND-IF C),
+ or (A OR[-IF] (B OR-IF C) -> ((A OR B) OR-IF C). */
+ else if (TREE_CODE (arg1) == icode
+ && simple_operand_p_2 (arg0)
+ /* Needed for sequence points to handle trappings, and
+ side-effects. */
+ && simple_operand_p_2 (TREE_OPERAND (arg1, 0)))
+ {
+ tem = fold_build2_loc (loc, ncode, type,
+ arg0, TREE_OPERAND (arg1, 0));
+ return fold_build2_loc (loc, icode, type, tem,
+ TREE_OPERAND (arg1, 1));
+ }
+ /* Transform (A AND-IF B) into (A AND B), or (A OR-IF B)
+ into (A OR B).
+ For sequence point consistancy, we need to check for trapping,
+ and side-effects. */
+ else if (code == icode && simple_operand_p_2 (arg0)
+ && simple_operand_p_2 (arg1))
+ return fold_build2_loc (loc, ncode, type, arg0, arg1);
+ }
+
return NULL_TREE;
}
@@ -10692,9 +10769,9 @@ fold_binary_loc (location_t loc,
}
}
- /* Optimize x*x as pow(x,2.0), which is expanded as x*x. */
+ /* Canonicalize x*x as pow(x,2.0), which is expanded as x*x. */
if (!in_gimple_form
- && optimize_function_for_speed_p (cfun)
+ && optimize
&& operand_equal_p (arg0, arg1, 0))
{
tree powfn = mathfn_built_in (type, BUILT_IN_POW);
@@ -13646,7 +13723,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
case BIT_FIELD_REF:
if ((TREE_CODE (arg0) == VECTOR_CST
- || (TREE_CODE (arg0) == CONSTRUCTOR && TREE_CONSTANT (arg0)))
+ || TREE_CODE (arg0) == CONSTRUCTOR)
&& type == TREE_TYPE (TREE_TYPE (arg0)))
{
unsigned HOST_WIDE_INT width = tree_low_cst (arg1, 1);
@@ -13658,24 +13735,17 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
&& (idx = idx / width)
< TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)))
{
- tree elements = NULL_TREE;
-
if (TREE_CODE (arg0) == VECTOR_CST)
- elements = TREE_VECTOR_CST_ELTS (arg0);
- else
{
- unsigned HOST_WIDE_INT idx;
- tree value;
-
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg0), idx, value)
- elements = tree_cons (NULL_TREE, value, elements);
+ tree elements = TREE_VECTOR_CST_ELTS (arg0);
+ while (idx-- > 0 && elements)
+ elements = TREE_CHAIN (elements);
+ if (elements)
+ return TREE_VALUE (elements);
}
- while (idx-- > 0 && elements)
- elements = TREE_CHAIN (elements);
- if (elements)
- return TREE_VALUE (elements);
- else
- return build_zero_cst (type);
+ else if (idx < CONSTRUCTOR_NELTS (arg0))
+ return CONSTRUCTOR_ELT (arg0, idx)->value;
+ return build_zero_cst (type);
}
}
@@ -13886,11 +13956,7 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx, htab_t ht)
union tree_node buf;
int i, len;
-recursive_label:
-
- gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
- <= sizeof (struct tree_function_decl))
- && sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
+ recursive_label:
if (expr == NULL)
return;
slot = (void **) htab_find_slot (ht, expr, INSERT);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index c6bea2a28f7..a350ff29a38 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,393 @@
+2011-10-19 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * check.c (gfc_check_sizeof): Reject procedures as argument of SIZEOF.
+ * intrinsinc.texi (SIZEOF): Document it.
+ (STORAGE_SIZE): Fix special characters. Fix line breaks.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans.c (gfc_build_array_ref): If type is not an array, check that
+ there is nothing to do, and do nothing.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-types.c (gfc_build_array_type): Don't force lower bound to one
+ in the deferred case.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * simplify.c (simplify_cobound): Accept non-last-in-ref-chain coarrays.
+ Don't set already set array ref.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * array.c (gfc_find_array_ref): Remove coarray-specific handling.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * check.c (dim_corank_check): Use gfc_get_corank to get corank.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-intrinsic.c (walk_coarray): Change AR_ELEMENT to AR_SECTION.
+
+ PR fortran/50420
+ * trans-intrinsic.c (walk_coarray): Use gfc_walk_array_ref for
+ the scalarization chain initialization.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-intrinsic.c (walk_coarray): Allow subreferences after a
+ coarray object reference.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-array.c (gfc_walk_array_ref): Allow zero rank arrays
+ if they are coarrays.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.h (gfc_walk_array_ref): New prototype.
+ * trans-array.c (gfc_walk_array_ref): New function, containing
+ all but the beginning of gfc_walk_variable_expr's code.
+ (gfc_walk_variable_expr): Use gfc_walk_array_ref.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-array.c (gfc_conv_expr_descriptor): Use loop.dimen instead of
+ ndim for the descriptor's rank.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-array.c (gfc_conv_expr_descriptor): Count codimensions starting
+ from zero, and add then the relevant offset (either ndim or loop.dimen)
+ depending on context.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Save some horizontal space.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Move ndim initialization
+ earlier.
+
+2011-10-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * decl.c (verify_c_interop_param): Renamed to
+ 'gfc_verify_c_interop_param'. Add error message for polymorphic
+ arguments.
+ (verify_c_interop): Renamed to 'gfc_verify_c_interop'. Reject
+ polymorphic variables.
+ (verify_bind_c_sym): Renamed 'verify_c_interop'.
+ * gfortran.h (verify_c_interop,verify_c_interop_param): Renamed.
+ * check.c (gfc_check_sizeof): Ditto.
+ * resolve.c (gfc_iso_c_func_interface,resolve_fl_procedure): Ditto.
+ * symbol.c (verify_bind_c_derived_type): Ditto.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * cpp.c (print_line, cb_define): Adjust to avoid using internals
+ of struct line_map. Use the public API instead.
+
+2011-10-17 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ PR fortran/50752
+ * primary.c (match_kind_param): Avoid segfault.
+
+2011-10-16 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * frontend-passes.c (current_ns): Make static.
+ (create_var): Note parent of newly created namespace.
+ (optimize_namespace): Don't wak sibling namespaces
+ if they are EXEC_BLOCK because this is handled...
+ (gfc_code_walker): ... here. Also walk ASSOCIATE lists.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * primary.c (match_kind_param): Detect ISO_C_BINDING kinds.
+ (get_kind): Pass on 'is_iso_c' flag.
+ (match_integer_constant,match_real_constant,match_logical_constant):
+ Set 'ts.is_c_interop'.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50547
+ * resolve.c (resolve_formal_arglist): Remove unneeded error message.
+ Some reshuffling.
+
+2011-10-15 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.texi (Fortran 2008 status, TS 29113 status,
+ Further Interoperability of Fortran with C): Update implementation
+ status, change references from TR 29113 to TS 29113.
+ * intrinsic.texi (RANK): Change TR 29113 to TS 29113.
+ * invoke.text (-std=): Ditto, change -std=f2008tr to -std=f2008ts.
+ * lang.opt (std=): Ditto.
+ * options.c (gfc_handle_option, set_default_std_flags): Ditto and
+ change GFC_STD_F2008_TR to GFC_STD_F2008_TS.
+ * libgfortran.h: Ditto.
+ * intrinsic.c (add_functions, gfc_check_intrinsic_standard): Ditto.
+ * decl.c (verify_c_interop_param): Ditto.
+
+2011-10-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50570
+ * expr.c (gfc_check_vardef_context): Don't throw an error on
+ non-pointer assignments involving an intent(in) pointer dummy.
+
+2011-10-14 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50718
+ * trans-expr.c (gfc_conv_procedure_call): Fix -fcheck=pointer
+ for dummy arguments with VALUE attribute.
+
+2011-10-11 Tobias Burnus <burnus@net-b.de>
+ Janus Weil <janus@gcc.gnu.org>
+
+ * invoke.texi (-fwhole-file): Update wording since -fwhole-file
+ is now enabled by default.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * trans-expr.c (gfc_conv_power_op): Delete old interface with two
+ parallel arrays to hold standard builtin declarations, and replace
+ it with a function based interface that can support creating
+ builtins on the fly in the future. Change all uses, and poison
+ the old names. Make sure 0 is not a legitimate builtin index.
+ (fill_with_spaces): Ditto.
+ (gfc_trans_string_copy): Ditto.
+ (gfc_trans_zero_assign): Ditto.
+ (gfc_build_memcpy_call): Ditto.
+ (alloc_scalar_allocatable_for_assignment): Ditto.
+ * trans-array.c (gfc_trans_array_constructor_value): Ditto.
+ (duplicate_allocatable): Ditto.
+ (gfc_alloc_allocatable_for_assignment): Ditto.
+ * trans-openmp.c (gfc_omp_clause_copy_ctor): Ditto.
+ (gfc_omp_clause_assign_op): Ditto.
+ (gfc_trans_omp_atomic): Ditto.
+ (gfc_trans_omp_do): Ditto.
+ (gfc_trans_omp_task): Ditto.
+ * trans-stmt.c (gfc_trans_stop): Ditto.
+ (gfc_trans_sync): Ditto.
+ (gfc_trans_allocate): Ditto.
+ (gfc_trans_deallocate): Ditto.
+ * trans.c (gfc_call_malloc): Ditto.
+ (gfc_allocate_using_malloc): Ditto.
+ (gfc_call_free): Ditto.
+ (gfc_deallocate_with_status): Ditto.
+ (gfc_deallocate_scalar_with_status): Ditto.
+ * f95-lang.c (gfc_define_builtin): Ditto.
+ (gfc_init_builtin_functions): Ditto.
+ * trans-decl.c (create_main_function): Ditto.
+ * trans-intrinsic.c (builtin_decl_for_precision): Ditto.
+
+2011-10-10 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/50564
+ * frontend-passes (forall_level): New variable.
+ (cfe_register_funcs): Don't register functions if we
+ are within a forall loop.
+ (optimize_namespace): Set forall_level to 0 before entry.
+ (gfc_code_walker): Increase/decrease forall_level.
+
+2011-10-09 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50273
+ * trans-common.c (translate_common): Fix -Walign-commons check.
+
+2011-10-09 Mikael Morin <mikael.morin@sfr.fr>
+
+ * interface.c (check_dummy_characteristics): Count dimensions starting
+ from one in diagnostic.
+
+2011-10-09 Tobias Burnus <burnus@net-b.de>
+
+ * Make-lang.in (F95_PARSER_OBJS, GFORTRAN_TRANS_DEPS): Add
+ dependency on iso-c-binding.def and iso-fortran-env.def.
+ * module.c (import_iso_c_binding_module): Add error when
+ explicitly importing a nonstandard symbol; extend standard-
+ depending loading.
+ * iso-c-binding.def: Add c_float128 and c_float128_complex
+ integer parameters (for -std=gnu).
+ * intrinsic.texi (ISO_C_Binding): Document them.
+ * symbol.c (generate_isocbinding_symbol): Change macros
+ to ignore GFC_STD_* data.
+ * trans-types.c (gfc_init_c_interop_kinds): Ditto; make
+ nonstatic and renamed from "init_c_interop_kinds".
+ (gfc_init_kinds): Don't call it
+ * trans-types.h (gfc_init_c_interop_kinds): Add prototype.
+ * f95-lang.c (gfc_init_decl_processing): Call it.
+
+2011-10-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50659
+ * expr.c (replace_symbol): Only do replacement if the symbol is a dummy.
+
+2011-10-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/47844
+ * trans-array.c (gfc_conv_array_index_offset): Use descriptor
+ stride for pointer function results.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Remove trailing whitespace.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_ss_startstride): Merge two switch cases.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_section_startstride): Remove coarray argument.
+ Remove conditions on coarray.
+ (gfc_conv_ss_startstride): Update call to gfc_conv_section_startstride.
+ (gfc_conv_expr_descriptor): Ditto. Add assertions before the call.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_section_startstride): Remove coarray_last
+ argument. Remove condition on coarray_last.
+ (gfc_conv_ss_startstride): Update call to gfc_conv_section_startstride.
+ (gfc_conv_expr_descriptor): Ditto.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_walk_variable_expr): Remove scalar coarray
+ handling. Don't reset array ref's corank and codimensions' types
+ in the full array ref case. Update loop upper limit.
+ Remove DIMEN_THIS_IMAGE case. Remove unnecessary conditions.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans.h (gfc_ss_info): Remove codimen field.
+ * trans-array.c (gfc_get_array_ss): Don't set codimen field.
+ (gfc_trans_create_temp_array): Don't set descriptor's cobounds.
+ (gfc_trans_constant_array_constructor): Update loop upper limit.
+ (gfc_conv_ss_startstride): Don't set codimen field.
+ Don't get descriptor's cobounds.
+ (gfc_walk_variable_expr): Update dimension index.
+ * trans-intrinsic.c (trans_this_image, trans_image_index,
+ conv_intrinsic_cobound): Don't set codimen field
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans.h (gfc_loopinfo): Remove codimen field.
+ * trans-array.c (gfc_set_vector_loop_bounds,
+ gfc_trans_scalarizing_loops, gfc_conv_loop_setup): Update loop upper
+ limit.
+ (gfc_set_loop_bounds_from_array_spec): Ditto. Remove skip on last
+ codimension.
+ (gfc_start_scalarized_body): Update loop lower limit.
+ (gfc_conv_ss_startstride): Don't set loop's codimen field.
+ (gfc_conv_loop_setup): Remove unnecessary condition.
+ (gfc_conv_expr_descriptor): Don't use loop's codimen field as corank.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans.h (gfc_ss): Remove data.temp.codimen field.
+ * trans-array.c (gfc_conv_resolve_dependencies,
+ gfc_conv_expr_descriptor): Don't set temp's codimen field.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * resolve.c (resolve_array_ref): Set array_ref's dimen field (and the
+ associated dimen_type) in the full array ref case.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-intrinsic.c (walk_coarray): New function.
+ (convert_element_to_coarray_ref): Move code to walk_coarray. Remove.
+ (trans-this_image, trans_image_index, conv_intrinsic_cobound):
+ Use walk_coarray.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Add out-of-the-scalarizer
+ cobounds evaluation.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_ss_startstride): Support zero rank loop.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_section_startstride): Move code to
+ evaluate_bound. Use evaluate_bound.
+ (evaluate_bound): New function.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_section_startstride): Update assertion to
+ also accept coarrays.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_section_startstride): Factor common
+ array ref references.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Use codim instead of
+ loop.codimen as argument to gfc_get_array_type_bounds.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.h (struct gfc_se): New flag want_coarray.
+ * trans-intrinsic.c (trans_this_image, trans_image_index,
+ conv_intrinsic_cobound): Set want_coarray.
+ * trans_array.c (gfc_conv_expr_descriptor): Evaluate codimension
+ earlier and without relying on the scalarizer.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * expr.c (gfc_get_corank): Return 0 if input expression is not a
+ coarray.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Simplify coarray
+ descriptor setup code.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * resolve.c (compare_spec_to_ref): Move coarray ref initialization
+ code...
+ (resolve_array_ref): ... here.
+
+2011-10-07 Mikael Morin <mikael.morin@sfr.fr>
+
+ * check.c (is_coarray): Remove.
+ (coarray_check): Use gfc_is_coarray.
+
+2011-10-07 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50625
+ * class.c (gfc_build_class_symbol): Fix whitespace.
+ * module.c (mio_symbol): Set 'class_ok' attribute.
+ * trans-decl.c (gfc_get_symbol_decl): Make sure the backend_decl has
+ been built for class symbols.
+
+2011-10-04 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/35831
+ * interface.c (check_dummy_characteristics): Check the array shape.
+
2011-10-01 Janus Weil <janus@gcc.gnu.org>
PR fortran/50585
@@ -202,7 +592,7 @@
* symbol.c (check_conflict): Allow threadprivate attribute with
FL_PROCEDURE if proc_pointer.
-2011-08-25 Mikael Morin <mikael.morin@gcc.gnu.org>
+2011-08-25 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/50050
* expr.c (gfc_free_shape): Do nothing if shape is NULL.
@@ -252,7 +642,7 @@
* cpp.c (gfc_cpp_init): Force BUILTINS_LOCATION for tokens
defined in cpp_define_builtins.
-2011-08-22 Mikael Morin <mikael.morin@gcc.gnu.org>
+2011-08-22 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/50050
* gfortran.h (gfc_clear_shape, gfc_free_shape): New prototypes.
diff --git a/gcc/fortran/ChangeLog-2008 b/gcc/fortran/ChangeLog-2008
index 7f536aa446c..6fe1eea164d 100644
--- a/gcc/fortran/ChangeLog-2008
+++ b/gcc/fortran/ChangeLog-2008
@@ -45,7 +45,7 @@
* trans-intrinsic.c (conv_same_strlen_check): New method.
(gfc_conv_intrinsic_merge): Call it here to actually do the check.
-2008-12-15 Mikael Morin <mikael.morin@tele2.fr>
+2008-12-15 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/38487
* dependency.c (gfc_is_data_pointer): New function.
@@ -53,7 +53,7 @@
in the pointer case.
(gfc_check_dependency): Use gfc_is_data_pointer.
-2008-12-15 Mikael Morin <mikael.morin@tele2.fr>
+2008-12-15 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/38113
* error.c (show_locus): Start counting columns at 0.
@@ -98,13 +98,13 @@
* invoke.texi (idirafter): New.
(no-range-check): Fixed entry in option-index.
-2008-12-09 Mikael Morin <mikael.morin@tele2.fr>
+2008-12-09 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/37469
* expr.c (find_array_element): Simplify array bounds.
Assert that both bounds are constant expressions.
-2008-12-09 Mikael Morin <mikael.morin@tele2.fr>
+2008-12-09 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/35983
* trans-expr.c (gfc_trans_subcomponent_assign):
@@ -158,7 +158,7 @@
* trans-types.c (gfc_sym_type,gfc_get_function_type): Support procedure
pointers as function result.
-2008-12-01 Mikael Morin <mikael.morin@tele2.fr>
+2008-12-01 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/38252
* parse.c (parse_spec): Skip statement order check in case
@@ -193,7 +193,7 @@
* module.c (gfc_dump_module): Report error on unlink only if
errno != ENOENT.
-2008-11-25 Mikael Morin <mikael.morin@tele2.fr>
+2008-11-25 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/36463
* expr.c (replace_symbol): Don't replace the symtree
@@ -218,7 +218,7 @@
* arith.c (gfc_check_real_range): Add mpfr_check_range.
* simplify.c (gfc_simplify_nearest): Add mpfr_check_range.
-2008-11-24 Mikael Morin <mikael.morin@tele2.fr>
+2008-11-24 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/38184
* simplify.c (is_constant_array_expr): Return true instead of false
@@ -308,7 +308,7 @@
* module.c (load_equiv): Regression fix; check that equivalence
members come from the same module only.
-2008-11-16 Mikael Morin <mikael.morin@tele2.fr>
+2008-11-16 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/35681
* dependency.c (gfc_check_argument_var_dependency): Add
@@ -333,7 +333,7 @@
* dependency.h (enum gfc_dep_check): New enum.
(gfc_check_fncall_dependency): Update prototype.
-2008-11-16 Mikael Morin <mikael.morin@tele2.fr>
+2008-11-16 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/37992
* gfortran.h (gfc_namespace): Added member old_cl_list,
@@ -518,7 +518,7 @@
* fortran/check.c (gfc_check_random_seed): Check PUT size
at compile time.
-2008-10-31 Mikael Morin <mikael.morin@tele2.fr>
+2008-10-31 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/35840
* expr.c (gfc_reduce_init_expr): New function, containing checking code
@@ -528,7 +528,7 @@
checking that the expression is a constant.
* match.h (gfc_reduce_init_expr): Prototype added.
-2008-10-31 Mikael Morin <mikael.morin@tele2.fr>
+2008-10-31 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/35820
* resolve.c (gfc_count_forall_iterators): New function.
@@ -548,7 +548,7 @@
gfc_simplify_ifix, gfc_simplify_idint, simplify_nint): Update function
calls to include locus.
-2008-10-30 Mikael Morin <mikael.morin@tele2.fr>
+2008-10-30 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/37903
* trans-array.c (gfc_trans_create_temp_array): If n is less
@@ -563,7 +563,7 @@
possible. Calculate the translation from loop variables to
array indices if an array constructor.
-2008-10-30 Mikael Morin <mikael.morin@tele2.fr>
+2008-10-30 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/37749
* trans-array.c (gfc_trans_create_temp_array): If size is NULL
diff --git a/gcc/fortran/ChangeLog-2009 b/gcc/fortran/ChangeLog-2009
index 43d206a14b7..c5b7e621ba6 100644
--- a/gcc/fortran/ChangeLog-2009
+++ b/gcc/fortran/ChangeLog-2009
@@ -3519,7 +3519,7 @@
* intrinsic.texi (MALLOC): Make example more portable.
-2009-02-13 Mikael Morin <mikael.morin@tele2.fr>
+2009-02-13 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/38259
* module.c (gfc_dump_module,gfc_use_module): Add module
@@ -3566,7 +3566,7 @@
* invoke.texi (RANGE): RANGE also takes INTEGER arguments.
-2009-01-19 Mikael Morin <mikael.morin@tele2.fr>
+2009-01-19 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/38859
* simplify.c (simplify_bound): Don't use array specification
@@ -3656,7 +3656,7 @@
is substituted by a function.
* resolve.c (check_host_association): Return if above is set.
-2009-01-04 Mikael Morin <mikael.morin@tele2.fr>
+2009-01-04 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/35681
* ChangeLog-2008: Fix function name.
@@ -3681,7 +3681,7 @@
* intrinsic.h (gfc_simplify_merge): New prototype.
* intrinsic.c (add_functions): Added simplification for MERGE.
-2009-01-04 Mikael Morin <mikael.morin@tele2.fr>
+2009-01-04 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/38536
* gfortran.h (gfc_is_data_pointer): Added prototype
diff --git a/gcc/fortran/ChangeLog-2010 b/gcc/fortran/ChangeLog-2010
index 9110670693a..dc25cbd39b9 100644
--- a/gcc/fortran/ChangeLog-2010
+++ b/gcc/fortran/ChangeLog-2010
@@ -71,7 +71,7 @@
substring references.
(gfc_check_same_strlen): Use gfc_var_strlen.
-2010-12-23 Mikael Morin <mikael.morin@gcc.gnu.org>
+2010-12-23 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/46978
Revert part of revision 164112
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index 08164587d0b..b766da651a2 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -329,14 +329,16 @@ $(F95_PARSER_OBJS): fortran/gfortran.h fortran/libgfortran.h \
fortran/parse.h fortran/arith.h fortran/target-memory.h \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TM_P_H) coretypes.h \
$(RTL_H) $(TREE_H) $(TREE_DUMP_H) $(GGC_H) $(EXPR_H) \
- $(FLAGS_H) output.h $(DIAGNOSTIC_H) errors.h $(FUNCTION_H)
+ $(FLAGS_H) output.h $(DIAGNOSTIC_H) errors.h $(FUNCTION_H) \
+ fortran/iso-c-binding.def fortran/iso-fortran-env.def
fortran/openmp.o: pointer-set.h $(TARGET_H) toplev.h
GFORTRAN_TRANS_DEPS = fortran/gfortran.h fortran/libgfortran.h \
fortran/intrinsic.h fortran/trans-array.h \
fortran/trans-const.h fortran/trans-const.h fortran/trans.h \
fortran/trans-stmt.h fortran/trans-types.h \
- $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) coretypes.h $(GGC_H)
+ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) coretypes.h $(GGC_H) \
+ fortran/iso-c-binding.def fortran/iso-fortran-env.def
fortran/f95-lang.o: $(GFORTRAN_TRANS_DEPS) fortran/mathbuiltins.def \
gt-fortran-f95-lang.h gtype-fortran.h $(CGRAPH_H) $(TARGET_H) fortran/cpp.h \
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index aa9cc0c3ab3..3e6b9d2591c 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -2296,8 +2296,7 @@ gfc_find_array_ref (gfc_expr *e)
for (ref = e->ref; ref; ref = ref->next)
if (ref->type == REF_ARRAY
- && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION
- || (ref->u.ar.type == AR_ELEMENT && ref->u.ar.dimen == 0)))
+ && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION))
break;
if (ref == NULL)
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index b1fc38accb8..bf4559203b1 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -203,42 +203,10 @@ double_check (gfc_expr *d, int n)
}
-/* Check whether an expression is a coarray (without array designator). */
-
-static bool
-is_coarray (gfc_expr *e)
-{
- bool coarray = false;
- gfc_ref *ref;
-
- if (e->expr_type != EXPR_VARIABLE)
- return false;
-
- coarray = e->symtree->n.sym->attr.codimension;
-
- for (ref = e->ref; ref; ref = ref->next)
- {
- if (ref->type == REF_COMPONENT)
- coarray = ref->u.c.component->attr.codimension;
- else if (ref->type != REF_ARRAY || ref->u.ar.dimen != 0)
- coarray = false;
- else if (ref->type == REF_ARRAY && ref->u.ar.codimen != 0)
- {
- int n;
- for (n = 0; n < ref->u.ar.codimen; n++)
- if (ref->u.ar.dimen_type[n] != DIMEN_THIS_IMAGE)
- coarray = false;
- }
- }
-
- return coarray;
-}
-
-
static gfc_try
coarray_check (gfc_expr *e, int n)
{
- if (!is_coarray (e))
+ if (!gfc_is_coarray (e))
{
gfc_error ("Expected coarray variable as '%s' argument to the %s "
"intrinsic at %L", gfc_current_intrinsic_arg[n]->name,
@@ -543,7 +511,6 @@ dim_check (gfc_expr *dim, int n, bool optional)
static gfc_try
dim_corank_check (gfc_expr *dim, gfc_expr *array)
{
- gfc_array_ref *ar;
int corank;
gcc_assert (array->expr_type == EXPR_VARIABLE);
@@ -551,8 +518,7 @@ dim_corank_check (gfc_expr *dim, gfc_expr *array)
if (dim->expr_type != EXPR_CONSTANT)
return SUCCESS;
- ar = gfc_find_array_ref (array);
- corank = ar->as->corank;
+ corank = gfc_get_corank (array);
if (mpz_cmp_ui (dim->value.integer, 1) < 0
|| mpz_cmp_ui (dim->value.integer, corank) > 0)
@@ -3478,8 +3444,15 @@ gfc_check_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
gfc_try
-gfc_check_sizeof (gfc_expr *arg ATTRIBUTE_UNUSED)
+gfc_check_sizeof (gfc_expr *arg)
{
+ if (arg->ts.type == BT_PROCEDURE)
+ {
+ gfc_error ("'%s' argument of '%s' intrinsic at %L may not be a procedure",
+ gfc_current_intrinsic_arg[0]->name, gfc_current_intrinsic,
+ &arg->where);
+ return FAILURE;
+ }
return SUCCESS;
}
@@ -3487,7 +3460,7 @@ gfc_check_sizeof (gfc_expr *arg ATTRIBUTE_UNUSED)
gfc_try
gfc_check_c_sizeof (gfc_expr *arg)
{
- if (verify_c_interop (&arg->ts) != SUCCESS)
+ if (gfc_verify_c_interop (&arg->ts) != SUCCESS)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L must be an "
"interoperable data entity",
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 572011f45f6..f64cc1b2a81 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -188,7 +188,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
/* Class container has already been built. */
return SUCCESS;
- attr->class_ok = attr->dummy || attr->pointer || attr->allocatable;
+ attr->class_ok = attr->dummy || attr->pointer || attr->allocatable;
if (!attr->class_ok)
/* We can not build the class container yet. */
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 9368d890973..2f18893313b 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -818,27 +818,29 @@ print_line (source_location src_loc, const char *special_flags)
if (!gfc_cpp_option.no_line_commands)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
-
- size_t to_file_len = strlen (map->to_file);
- unsigned char *to_file_quoted =
- (unsigned char *) alloca (to_file_len * 4 + 1);
+ expanded_location loc;
+ size_t to_file_len;
+ unsigned char *to_file_quoted;
unsigned char *p;
- print.src_line = SOURCE_LINE (map, src_loc);
+ loc = expand_location (src_loc);
+ to_file_len = strlen (loc.file);
+ to_file_quoted = (unsigned char *) alloca (to_file_len * 4 + 1);
+
+ print.src_line = loc.line;
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
- (const unsigned char *) map->to_file, to_file_len);
+ (const unsigned char *) loc.file, to_file_len);
*p = '\0';
fprintf (print.outf, "# %u \"%s\"%s",
print.src_line == 0 ? 1 : print.src_line,
to_file_quoted, special_flags);
- if (map->sysp == 2)
+ if (loc.sysp == 2)
fputs (" 3 4", print.outf);
- else if (map->sysp == 1)
+ else if (loc.sysp == 1)
fputs (" 3", print.outf);
putc ('\n', print.outf);
@@ -935,7 +937,7 @@ cb_define (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- if (linemap_lookup (line_table, line)->to_line != 0)
+ if (LOCATION_LINE (line) != 0)
print.src_line++;
}
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 0ee25759113..2dd38b9485e 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -961,7 +961,7 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry)
across platforms. */
gfc_try
-verify_c_interop_param (gfc_symbol *sym)
+gfc_verify_c_interop_param (gfc_symbol *sym)
{
int is_c_interop = 0;
gfc_try retval = SUCCESS;
@@ -1000,20 +1000,24 @@ verify_c_interop_param (gfc_symbol *sym)
{
if (sym->ns->proc_name->attr.is_bind_c == 1)
{
- is_c_interop =
- (verify_c_interop (&(sym->ts))
- == SUCCESS ? 1 : 0);
+ is_c_interop = (gfc_verify_c_interop (&(sym->ts)) == SUCCESS ? 1 : 0);
if (is_c_interop != 1)
{
/* Make personalized messages to give better feedback. */
if (sym->ts.type == BT_DERIVED)
- gfc_error ("Type '%s' at %L is a parameter to the BIND(C) "
- "procedure '%s' but is not C interoperable "
+ gfc_error ("Variable '%s' at %L is a dummy argument to the "
+ "BIND(C) procedure '%s' but is not C interoperable "
"because derived type '%s' is not C interoperable",
sym->name, &(sym->declared_at),
sym->ns->proc_name->name,
sym->ts.u.derived->name);
+ else if (sym->ts.type == BT_CLASS)
+ gfc_error ("Variable '%s' at %L is a dummy argument to the "
+ "BIND(C) procedure '%s' but is not C interoperable "
+ "because it is polymorphic",
+ sym->name, &(sym->declared_at),
+ sym->ns->proc_name->name);
else
gfc_warning ("Variable '%s' at %L is a parameter to the "
"BIND(C) procedure '%s' but may not be C "
@@ -1069,7 +1073,7 @@ verify_c_interop_param (gfc_symbol *sym)
retval = FAILURE;
}
else if (sym->attr.optional == 1
- && gfc_notify_std (GFC_STD_F2008_TR, "TR29113: Variable '%s' "
+ && gfc_notify_std (GFC_STD_F2008_TS, "TS29113: Variable '%s' "
"at %L with OPTIONAL attribute in "
"procedure '%s' which is BIND(C)",
sym->name, &(sym->declared_at),
@@ -3711,11 +3715,13 @@ set_com_block_bind_c (gfc_common_head *com_block, int is_bind_c)
/* Verify that the given gfc_typespec is for a C interoperable type. */
gfc_try
-verify_c_interop (gfc_typespec *ts)
+gfc_verify_c_interop (gfc_typespec *ts)
{
if (ts->type == BT_DERIVED && ts->u.derived != NULL)
return (ts->u.derived->ts.is_c_interop || ts->u.derived->attr.is_bind_c)
? SUCCESS : FAILURE;
+ else if (ts->type == BT_CLASS)
+ return FAILURE;
else if (ts->is_c_interop != 1)
return FAILURE;
@@ -3788,7 +3794,7 @@ verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
the given ts (current_ts), so look in both. */
if (tmp_sym->ts.type != BT_UNKNOWN || ts->type != BT_UNKNOWN)
{
- if (verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
+ if (gfc_verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
{
/* See if we're dealing with a sym in a common block or not. */
if (is_in_common == 1)
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 813a99d037b..504c7cf7d6b 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -4134,8 +4134,9 @@ gfc_expr_check_typed (gfc_expr* e, gfc_namespace* ns, bool strict)
return error_found ? FAILURE : SUCCESS;
}
-/* Walk an expression tree and replace all symbols with a corresponding symbol
- in the formal_ns of "sym". Needed for copying interfaces in PROCEDURE
+
+/* Walk an expression tree and replace all dummy symbols by the corresponding
+ symbol in the formal_ns of "sym". Needed for copying interfaces in PROCEDURE
statements. The boolean return value is required by gfc_traverse_expr. */
static bool
@@ -4144,14 +4145,12 @@ replace_symbol (gfc_expr *expr, gfc_symbol *sym, int *i ATTRIBUTE_UNUSED)
if ((expr->expr_type == EXPR_VARIABLE
|| (expr->expr_type == EXPR_FUNCTION
&& !gfc_is_intrinsic (expr->symtree->n.sym, 0, expr->where)))
- && expr->symtree->n.sym->ns == sym->ts.interface->formal_ns)
+ && expr->symtree->n.sym->ns == sym->ts.interface->formal_ns
+ && expr->symtree->n.sym->attr.dummy)
{
- gfc_symtree *stree;
- gfc_namespace *ns = sym->formal_ns;
- /* Don't use gfc_get_symtree as we prefer to fail badly if we don't find
- the symtree rather than create a new one (and probably fail later). */
- stree = gfc_find_symtree (ns ? ns->sym_root : gfc_current_ns->sym_root,
- expr->symtree->n.sym->name);
+ gfc_symtree *root = sym->formal_ns ? sym->formal_ns->sym_root
+ : gfc_current_ns->sym_root;
+ gfc_symtree *stree = gfc_find_symtree (root, expr->symtree->n.sym->name);
gcc_assert (stree);
stree->n.sym->attr = expr->symtree->n.sym->attr;
expr->symtree = stree;
@@ -4165,6 +4164,7 @@ gfc_expr_replace_symbols (gfc_expr *expr, gfc_symbol *dest)
gfc_traverse_expr (expr, dest, &replace_symbol, 0);
}
+
/* The following is analogous to 'replace_symbol', and needed for copying
interfaces for procedure pointer components. The argument 'sym' must formally
be a gfc_symbol, so that the function can be passed to gfc_traverse_expr.
@@ -4301,13 +4301,19 @@ gfc_get_corank (gfc_expr *e)
{
int corank;
gfc_ref *ref;
+
+ if (!gfc_is_coarray (e))
+ return 0;
+
corank = e->symtree->n.sym->as ? e->symtree->n.sym->as->corank : 0;
+
for (ref = e->ref; ref; ref = ref->next)
{
if (ref->type == REF_ARRAY)
corank = ref->u.ar.as->corank;
gcc_assert (ref->type != REF_SUBSTRING);
}
+
return corank;
}
@@ -4629,7 +4635,7 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
sym->name, context, &e->where);
return FAILURE;
}
- if (!pointer && !is_pointer)
+ if (!pointer && !is_pointer && !sym->attr.pointer)
{
if (context)
gfc_error ("Dummy argument '%s' with INTENT(IN) in variable"
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 648831f2607..57c01148fff 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -595,6 +595,7 @@ gfc_init_decl_processing (void)
/* Set up F95 type nodes. */
gfc_init_kinds ();
gfc_init_types ();
+ gfc_init_c_interop_kinds ();
}
@@ -638,7 +639,7 @@ gfc_builtin_function (tree decl)
#define ATTR_CONST_NOTHROW_LIST (ECF_NOTHROW | ECF_CONST)
static void
-gfc_define_builtin (const char *name, tree type, int code,
+gfc_define_builtin (const char *name, tree type, enum built_in_function code,
const char *library_name, int attr)
{
tree decl;
@@ -653,8 +654,7 @@ gfc_define_builtin (const char *name, tree type, int code,
DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
NULL, DECL_ATTRIBUTES (decl));
- built_in_decls[code] = decl;
- implicit_built_in_decls[code] = decl;
+ set_builtin_decl (code, decl, true);
}
@@ -1005,7 +1005,7 @@ gfc_init_builtin_functions (void)
size_type_node, NULL_TREE);
gfc_define_builtin ("__builtin_malloc", ftype, BUILT_IN_MALLOC,
"malloc", ATTR_NOTHROW_LEAF_LIST);
- DECL_IS_MALLOC (built_in_decls[BUILT_IN_MALLOC]) = 1;
+ DECL_IS_MALLOC (builtin_decl_explicit (BUILT_IN_MALLOC)) = 1;
ftype = build_function_type_list (pvoid_type_node,
size_type_node, pvoid_type_node,
@@ -1121,7 +1121,7 @@ gfc_init_builtin_functions (void)
gfc_define_builtin ("__builtin_trap", builtin_types[BT_FN_VOID],
BUILT_IN_TRAP, NULL, ATTR_NOTHROW_LEAF_LIST);
- TREE_THIS_VOLATILE (built_in_decls[BUILT_IN_TRAP]) = 1;
+ TREE_THIS_VOLATILE (builtin_decl_explicit (BUILT_IN_TRAP)) = 1;
gfc_define_builtin ("__emutls_get_address",
builtin_types[BT_FN_PTR_PTR],
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 16053e0742a..5b1a644e247 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -60,7 +60,11 @@ static gfc_code *inserted_block, **changed_statement;
/* The namespace we are currently dealing with. */
-gfc_namespace *current_ns;
+static gfc_namespace *current_ns;
+
+/* If we are within any forall loop. */
+
+static int forall_level;
/* Entry point - run all passes for a namespace. So far, only an
optimization pass is run. */
@@ -165,6 +169,12 @@ cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
|| (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
return 0;
+ /* We don't do function elimination within FORALL statements, it can
+ lead to wrong-code in certain circumstances. */
+
+ if (forall_level > 0)
+ return 0;
+
/* If we don't know the shape at compile time, we create an allocatable
temporary variable to hold the intermediate result, but only if
allocation on assignment is active. */
@@ -251,6 +261,7 @@ create_var (gfc_expr * e)
(*current_code)->next = NULL;
/* Insert the BLOCK at the right position. */
*current_code = inserted_block;
+ ns->parent = current_ns;
}
else
ns = inserted_block->ext.block.ns;
@@ -493,13 +504,18 @@ optimize_namespace (gfc_namespace *ns)
{
current_ns = ns;
+ forall_level = 0;
gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
+ /* BLOCKs are handled in the expression walker below. */
for (ns = ns->contained; ns; ns = ns->sibling)
- optimize_namespace (ns);
+ {
+ if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
+ optimize_namespace (ns);
+ }
}
/* Replace code like
@@ -1132,6 +1148,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
gfc_code *b;
gfc_actual_arglist *a;
gfc_code *co;
+ gfc_association_list *alist;
/* There might be statement insertions before the current code,
which must not affect the expression walker. */
@@ -1140,6 +1157,13 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
switch (co->op)
{
+
+ case EXEC_BLOCK:
+ WALK_SUBCODE (co->ext.block.ns->code);
+ for (alist = co->ext.block.assoc; alist; alist = alist->next)
+ WALK_SUBEXPR (alist->target);
+ break;
+
case EXEC_DO:
WALK_SUBEXPR (co->ext.iterator->var);
WALK_SUBEXPR (co->ext.iterator->start);
@@ -1193,6 +1217,8 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
WALK_SUBEXPR (fa->end);
WALK_SUBEXPR (fa->stride);
}
+ if (co->op == EXEC_FORALL)
+ forall_level ++;
break;
}
@@ -1335,6 +1361,10 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
WALK_SUBEXPR (b->expr2);
WALK_SUBCODE (b->next);
}
+
+ if (co->op == EXEC_FORALL)
+ forall_level --;
+
}
}
return 0;
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 54e0b20580d..da3477d7a0b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -610,8 +610,8 @@ iso_fortran_env_symbol;
#undef NAMED_DERIVED_TYPE
#define NAMED_INTCST(a,b,c,d) a,
-#define NAMED_REALCST(a,b,c) a,
-#define NAMED_CMPXCST(a,b,c) a,
+#define NAMED_REALCST(a,b,c,d) a,
+#define NAMED_CMPXCST(a,b,c,d) a,
#define NAMED_LOGCST(a,b,c) a,
#define NAMED_CHARKNDCST(a,b,c) a,
#define NAMED_CHARCST(a,b,c) a,
@@ -2581,8 +2581,8 @@ gfc_symtree* gfc_find_symtree_in_proc (const char *, gfc_namespace *);
int gfc_find_symbol (const char *, gfc_namespace *, int, gfc_symbol **);
int gfc_find_sym_tree (const char *, gfc_namespace *, int, gfc_symtree **);
int gfc_get_symbol (const char *, gfc_namespace *, gfc_symbol **);
-gfc_try verify_c_interop (gfc_typespec *);
-gfc_try verify_c_interop_param (gfc_symbol *);
+gfc_try gfc_verify_c_interop (gfc_typespec *);
+gfc_try gfc_verify_c_interop_param (gfc_symbol *);
gfc_try verify_bind_c_sym (gfc_symbol *, gfc_typespec *, int, gfc_common_head *);
gfc_try verify_bind_c_derived_type (gfc_symbol *);
gfc_try verify_com_block_vars_c_interop (gfc_common_head *);
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 389c05bfaab..f847df38409 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -772,7 +772,7 @@ compile option was used.
@menu
* Fortran 2003 status::
* Fortran 2008 status::
-* TR 29113 status::
+* TS 29113 status::
@end menu
@node Fortran 2003 status
@@ -1003,8 +1003,11 @@ the intrinsic module @code{ISO_FORTRAN_ENV}.
@code{ISO_C_BINDINGS} and @code{COMPILER_VERSION} and @code{COMPILER_OPTIONS}
of @code{ISO_FORTRAN_ENV}.
-@item Experimental coarray, use the @option{-fcoarray=single} or
-@option{-fcoarray=lib} flag to enable it.
+@item Coarray support for serial programs with @option{-fcoarray=single} flag
+and experimental support for multiple images with the @option{-fcoarray=lib}
+flag.
+
+@item The @code{DO CONCURRENT} construct is supported.
@item The @code{BLOCK} construct is supported.
@@ -1049,19 +1052,25 @@ arrays are supported for named constants (@code{PARAMETER}).
-@node TR 29113 status
-@section Fortran 29113 status
+@node TS 29113 status
+@section Technical Specification 29113 Status
-GNU Fortran supports some of the new features of the technical report (TR)
-29113 on Further Interoperability of Fortran with C.
-@uref{http://gcc.gnu.org/wiki/Fortran2008Status, wiki} has some information
-about the current TR 29113 implementation status. In particular, the
+GNU Fortran supports some of the new features of the Technical
+Specification (TS) 29113 on Further Interoperability of Fortran with C.
+The @uref{http://gcc.gnu.org/wiki/TS29113Status, wiki} has some information
+about the current TS 29113 implementation status. In particular, the
following is implemented.
@itemize
-@item The @option{-std=f2008} option.
-@item The OPTIONAL attribute is now allowed for dummy arguments of
-BIND(C) procedures.
+@item The @option{-std=f2008ts} option.
+
+@item The @code{OPTIONAL} attribute is allowed for dummy arguments
+of @code{BIND(C) procedures.}
+
+@item The RANK intrinsic is supported.
+
+@item GNU Fortran's implementation for variables with @code{ASYNCHRONOUS}
+attribute is compatible with TS 29113.
@end itemize
@@ -2446,15 +2455,13 @@ END MODULE m
Assumed-shape and allocatable arrays are passed using an array descriptor
(dope vector). The internal structure of the array descriptor used
by GNU Fortran is not yet documented and will change. There will also be
-a Technical Report (TR 29113) which standardizes an interoperable
+a Technical Specification (TS 29113) which standardizes an interoperable
array descriptor. Until then, you can use the Chasm Language
Interoperability Tools, @url{http://chasm-interop.sourceforge.net/},
which provide an interface to GNU Fortran's array descriptor.
-The technical report 29113 will presumably also include support for
-C-interoperable @code{OPTIONAL} and for assumed-rank and assumed-type
-dummy arguments. However, the TR has neither been approved nor implemented
-in GNU Fortran; therefore, these features are not yet available.
+GNU Fortran already supports the C-interoperable @code{OPTIONAL}
+attribute; for absent arguments, a @code{NULL} pointer is passed.
@@ -2620,9 +2627,9 @@ Possible values are (bitwise or-ed) @code{GFC_STD_F77} (1),
@code{GFC_STD_F95_OBS} (2), @code{GFC_STD_F95_DEL} (4), @code{GFC_STD_F95}
(8), @code{GFC_STD_F2003} (16), @code{GFC_STD_GNU} (32),
@code{GFC_STD_LEGACY} (64), @code{GFC_STD_F2008} (128),
-@code{GFC_STD_F2008_OBS} (256) and GFC_STD_F2008_TR (512). Default:
+@code{GFC_STD_F2008_OBS} (256) and GFC_STD_F2008_TS (512). Default:
@code{GFC_STD_F95_OBS | GFC_STD_F95_DEL | GFC_STD_F95 | GFC_STD_F2003
-| GFC_STD_F2008 | GFC_STD_F2008_TR | GFC_STD_F2008_OBS | GFC_STD_F77
+| GFC_STD_F2008 | GFC_STD_F2008_TS | GFC_STD_F2008_OBS | GFC_STD_F77
| GFC_STD_GNU | GFC_STD_LEGACY}.
@item @var{option}[1] @tab Standard-warning flag; prints a warning to
standard error. Default: @code{GFC_STD_F95_DEL | GFC_STD_LEGACY}.
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index aa075a90401..5308513b774 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "gfortran.h"
#include "match.h"
+#include "arith.h"
/* The current_interface structure holds information about the
interface currently being parsed. This structure is saved and
@@ -1071,13 +1072,51 @@ check_dummy_characteristics (gfc_symbol *s1, gfc_symbol *s2,
/* Check array shape. */
if (s1->as && s2->as)
{
+ int i, compval;
+ gfc_expr *shape1, *shape2;
+
if (s1->as->type != s2->as->type)
{
snprintf (errmsg, err_len, "Shape mismatch in argument '%s'",
s1->name);
return FAILURE;
}
- /* FIXME: Check exact shape. */
+
+ if (s1->as->type == AS_EXPLICIT)
+ for (i = 0; i < s1->as->rank + s1->as->corank; i++)
+ {
+ shape1 = gfc_subtract (gfc_copy_expr (s1->as->upper[i]),
+ gfc_copy_expr (s1->as->lower[i]));
+ shape2 = gfc_subtract (gfc_copy_expr (s2->as->upper[i]),
+ gfc_copy_expr (s2->as->lower[i]));
+ compval = gfc_dep_compare_expr (shape1, shape2);
+ gfc_free_expr (shape1);
+ gfc_free_expr (shape2);
+ switch (compval)
+ {
+ case -1:
+ case 1:
+ case -3:
+ snprintf (errmsg, err_len, "Shape mismatch in dimension %i of "
+ "argument '%s'", i + 1, s1->name);
+ return FAILURE;
+
+ case -2:
+ /* FIXME: Implement a warning for this case.
+ gfc_warning ("Possible shape mismatch in argument '%s'",
+ s1->name);*/
+ break;
+
+ case 0:
+ break;
+
+ default:
+ gfc_internal_error ("check_dummy_characteristics: Unexpected "
+ "result %i of gfc_dep_compare_expr",
+ compval);
+ break;
+ }
+ }
}
return SUCCESS;
@@ -1131,6 +1170,8 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
"of '%s'", name2);
return 0;
}
+
+ /* FIXME: Check array bounds and string length of result. */
}
if (s1->attr.pure && !s2->attr.pure)
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 5946ddd8be2..8f437cc05fe 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -2434,9 +2434,9 @@ add_functions (void)
make_generic ("range", GFC_ISYM_RANGE, GFC_STD_F95);
add_sym_1 ("rank", GFC_ISYM_RANK, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di,
- GFC_STD_F2008_TR, gfc_check_rank, gfc_simplify_rank, NULL,
+ GFC_STD_F2008_TS, gfc_check_rank, gfc_simplify_rank, NULL,
a, BT_REAL, dr, REQUIRED);
- make_generic ("rank", GFC_ISYM_RANK, GFC_STD_F2008_TR);
+ make_generic ("rank", GFC_ISYM_RANK, GFC_STD_F2008_TS);
add_sym_2 ("real", GFC_ISYM_REAL, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F77,
gfc_check_real, gfc_simplify_real, gfc_resolve_real,
@@ -3989,8 +3989,8 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
symstd_msg = "new in Fortran 2008";
break;
- case GFC_STD_F2008_TR:
- symstd_msg = "new in TR 29113";
+ case GFC_STD_F2008_TS:
+ symstd_msg = "new in TS 29113";
break;
case GFC_STD_GNU:
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 9adeeabf60d..084cd15ea6f 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -10222,7 +10222,7 @@ See @code{PRECISION} for an example.
@code{RANK(A)} returns the rank of a scalar or array data object.
@item @emph{Standard}:
-Technical Report (TR) 29113
+Technical Specification (TS) 29113
@item @emph{Class}:
Inquiry function
@@ -11459,7 +11459,8 @@ number of bytes occupied by the argument. If the argument has the
to is returned. If the argument is of a derived type with @code{POINTER}
or @code{ALLOCATABLE} components, the return value doesn't account for
the sizes of the data pointed to by these components. If the argument is
-polymorphic, the size according to the declared type is returned.
+polymorphic, the size according to the declared type is returned. The argument
+may not be a procedure or procedure pointer.
@item @emph{Example}:
@smallexample
@@ -11816,8 +11817,10 @@ Inquiry function
@end multitable
@item @emph{Return Value}:
-The result is a scalar integer with the kind type parameter speciï¬ed by KIND (or default integer type if KIND is missing). The result value is the size expressed in bits for an element of an array that
-has the dynamic type and type parameters of A.
+The result is a scalar integer with the kind type parameter specified by KIND
+(or default integer type if KIND is missing). The result value is the size
+expressed in bits for an element of an array that has the dynamic type and type
+parameters of A.
@item @emph{See also}:
@ref{C_SIZEOF}, @ref{SIZEOF}
@@ -13006,7 +13009,9 @@ type default integer, which can be used as KIND type parameters.
In addition to the integer named constants required by the Fortran 2003
standard, GNU Fortran provides as an extension named constants for the
128-bit integer types supported by the C compiler: @code{C_INT128_T,
-C_INT_LEAST128_T, C_INT_FAST128_T}.
+C_INT_LEAST128_T, C_INT_FAST128_T}. Furthermore, if @code{__float} is
+supported in C, the named constants @code{C_FLOAT128, C_FLOAT128_COMPLEX}
+are defined.
@multitable @columnfractions .15 .35 .35 .35
@item Fortran Type @tab Named constant @tab C type @tab Extension
@@ -13036,9 +13041,11 @@ C_INT_LEAST128_T, C_INT_FAST128_T}.
@item @code{REAL} @tab @code{C_FLOAT} @tab @code{float}
@item @code{REAL} @tab @code{C_DOUBLE} @tab @code{double}
@item @code{REAL} @tab @code{C_LONG_DOUBLE} @tab @code{long double}
+@item @code{REAL} @tab @code{C_FLOAT128} @tab @code{__float128} @tab Ext.
@item @code{COMPLEX}@tab @code{C_FLOAT_COMPLEX} @tab @code{float _Complex}
@item @code{COMPLEX}@tab @code{C_DOUBLE_COMPLEX}@tab @code{double _Complex}
@item @code{COMPLEX}@tab @code{C_LONG_DOUBLE_COMPLEX}@tab @code{long double _Complex}
+@item @code{REAL} @tab @code{C_FLOAT128_COMPLEX} @tab @code{__float128 _Complex} @tab Ext.
@item @code{LOGICAL}@tab @code{C_BOOL} @tab @code{_Bool}
@item @code{CHARACTER}@tab @code{C_CHAR} @tab @code{char}
@end multitable
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 41fee670a6c..5bb9b9dbbdf 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -164,7 +164,7 @@ and warnings}.
@item Code Generation Options
@xref{Code Gen Options,,Options for code generation conventions}.
@gccoptlist{-fno-automatic -ff2c -fno-underscoring @gol
--fwhole-file -fsecond-underscore @gol
+-fno-whole-file -fsecond-underscore @gol
-fbounds-check -fcheck-array-temporaries -fmax-array-constructor =@var{n} @gol
-fcheck=@var{<all|array-temps|bounds|do|mem|pointer|recursion>} @gol
-fcoarray=@var{<none|single|lib>} -fmax-stack-var-size=@var{n} @gol
@@ -368,9 +368,10 @@ extensions, and may be useful for old non-standard programs. The
conformance to the Fortran 95, Fortran 2003 and Fortran 2008 standards,
respectively; errors are given for all extensions beyond the relevant
language standard, and warnings are given for the Fortran 77 features
-that are permitted but obsolescent in later standards. @samp{-std=f2008tr}
+that are permitted but obsolescent in later standards. @samp{-std=f2008ts}
allows the Fortran 2008 standard including the additions of the
-technical report (TR) 29113.
+Technical Specification (TS) 29113 on Further Interoperability of Fortran
+with C.
@end table
@@ -1225,19 +1226,22 @@ in the source, even if the names as seen by the linker are mangled to
prevent accidental linking between procedures with incompatible
interfaces.
-@item -fwhole-file
-@opindex @code{fwhole-file}
-By default, GNU Fortran parses, resolves and translates each procedure
-in a file separately. Using this option modifies this such that the
-whole file is parsed and placed in a single front-end tree. During
-resolution, in addition to all the usual checks and fixups, references
+@item -fno-whole-file
+@opindex @code{fno-whole-file}
+This flag causes the compiler to resolve and translate each procedure in
+a file separately.
+
+By default, the whole file is parsed and placed in a single front-end tree.
+During resolution, in addition to all the usual checks and fixups, references
to external procedures that are in the same file effect resolution of
-that procedure, if not already done, and a check of the interfaces. The
+that procedure, if not already done, and a check of the interfaces. The
dependences are resolved by changing the order in which the file is
translated into the backend tree. Thus, a procedure that is referenced
is translated before the reference and the duplication of backend tree
declarations eliminated.
+The @option{-fno-whole-file} option is deprecated and may lead to wrong code.
+
@item -fsecond-underscore
@opindex @code{fsecond-underscore}
@cindex underscore
diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def
index bea83067bfe..f8673b963c8 100644
--- a/gcc/fortran/iso-c-binding.def
+++ b/gcc/fortran/iso-c-binding.def
@@ -24,11 +24,11 @@ along with GCC; see the file COPYING3. If not see
#endif
#ifndef NAMED_REALCST
-# define NAMED_REALCST(a,b,c)
+# define NAMED_REALCST(a,b,c,d)
#endif
#ifndef NAMED_CMPXCST
-# define NAMED_CMPXCST(a,b,c)
+# define NAMED_CMPXCST(a,b,c,d)
#endif
#ifndef NAMED_LOGCST
@@ -103,17 +103,25 @@ NAMED_INTCST (ISOCBINDING_INT_FAST128_T, "c_int_fast128_t",
get_int_kind_from_width (128), GFC_STD_GNU)
NAMED_REALCST (ISOCBINDING_FLOAT, "c_float", \
- get_real_kind_from_node (float_type_node))
+ get_real_kind_from_node (float_type_node), GFC_STD_F2003)
NAMED_REALCST (ISOCBINDING_DOUBLE, "c_double", \
- get_real_kind_from_node (double_type_node))
+ get_real_kind_from_node (double_type_node), GFC_STD_F2003)
NAMED_REALCST (ISOCBINDING_LONG_DOUBLE, "c_long_double", \
- get_real_kind_from_node (long_double_type_node))
+ get_real_kind_from_node (long_double_type_node), GFC_STD_F2003)
+NAMED_REALCST (ISOCBINDING_FLOAT128, "c_float128", \
+ float128_type_node == NULL_TREE \
+ ? -4 : get_real_kind_from_node (float128_type_node), \
+ GFC_STD_GNU)
NAMED_CMPXCST (ISOCBINDING_FLOAT_COMPLEX, "c_float_complex", \
- get_real_kind_from_node (float_type_node))
+ get_real_kind_from_node (float_type_node), GFC_STD_F2003)
NAMED_CMPXCST (ISOCBINDING_DOUBLE_COMPLEX, "c_double_complex", \
- get_real_kind_from_node (double_type_node))
+ get_real_kind_from_node (double_type_node), GFC_STD_F2003)
NAMED_CMPXCST (ISOCBINDING_LONG_DOUBLE_COMPLEX, "c_long_double_complex", \
- get_real_kind_from_node (long_double_type_node))
+ get_real_kind_from_node (long_double_type_node), GFC_STD_F2003)
+NAMED_CMPXCST (ISOCBINDING_FLOAT128_COMPLEX, "c_float128_complex", \
+ float128_type_node == NULL_TREE \
+ ? -4 : get_real_kind_from_node (float128_type_node), \
+ GFC_STD_GNU)
NAMED_LOGCST (ISOCBINDING_BOOL, "c_bool", \
get_int_kind_from_width (BOOL_TYPE_SIZE))
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 1a3d073b3fb..081041bebe7 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -590,9 +590,9 @@ std=f2008
Fortran
Conform to the ISO Fortran 2008 standard
-std=f2008tr
+std=f2008ts
Fortran
-Conform to the ISO Fortran 2008 standard including TR 29113
+Conform to the ISO Fortran 2008 standard including TS 29113
std=f95
Fortran
diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h
index b2137bbf80f..874cd9537bb 100644
--- a/gcc/fortran/libgfortran.h
+++ b/gcc/fortran/libgfortran.h
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
Note that no features were obsoleted nor deleted in F2003.
Please remember to keep those definitions in sync with
gfortran.texi. */
-#define GFC_STD_F2008_TR (1<<9) /* POST-F2008 technical reports. */
+#define GFC_STD_F2008_TS (1<<9) /* POST-F2008 technical reports. */
#define GFC_STD_F2008_OBS (1<<8) /* Obsolescent in F2008. */
#define GFC_STD_F2008 (1<<7) /* New in F2008. */
#define GFC_STD_LEGACY (1<<6) /* Backward compatibility. */
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index b29ba4b66ee..62f759876d3 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -3608,6 +3608,8 @@ mio_symbol (gfc_symbol *sym)
mio_symbol_attribute (&sym->attr);
mio_typespec (&sym->ts);
+ if (sym->ts.type == BT_CLASS)
+ sym->attr.class_ok = 1;
if (iomode == IO_OUTPUT)
mio_namespace_ref (&sym->formal_ns);
@@ -5348,8 +5350,53 @@ import_iso_c_binding_module (void)
for (u = gfc_rename_list; u; u = u->next)
if (strcmp (c_interop_kinds_table[i].name, u->use_name) == 0)
{
+ bool not_in_std;
+ const char *name;
u->found = 1;
found = true;
+
+ switch (i)
+ {
+#define NAMED_FUNCTION(a,b,c,d) \
+ case a: \
+ not_in_std = (gfc_option.allow_std & d) == 0; \
+ name = b; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_FUNCTION
+#define NAMED_INTCST(a,b,c,d) \
+ case a: \
+ not_in_std = (gfc_option.allow_std & d) == 0; \
+ name = b; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_INTCST
+#define NAMED_REALCST(a,b,c,d) \
+ case a: \
+ not_in_std = (gfc_option.allow_std & d) == 0; \
+ name = b; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_REALCST
+#define NAMED_CMPXCST(a,b,c,d) \
+ case a: \
+ not_in_std = (gfc_option.allow_std & d) == 0; \
+ name = b; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_CMPXCST
+ default:
+ not_in_std = false;
+ name = "";
+ }
+
+ if (not_in_std)
+ {
+ gfc_error ("The symbol '%s', referenced at %C, is not "
+ "in the selected standard", name);
+ continue;
+ }
+
switch (i)
{
#define NAMED_FUNCTION(a,b,c,d) \
@@ -5372,23 +5419,59 @@ import_iso_c_binding_module (void)
}
if (!found && !only_flag)
- switch (i)
- {
+ {
+ /* Skip, if the symbol is not in the enabled standard. */
+ switch (i)
+ {
+#define NAMED_FUNCTION(a,b,c,d) \
+ case a: \
+ if ((gfc_option.allow_std & d) == 0) \
+ continue; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_FUNCTION
+
+#define NAMED_INTCST(a,b,c,d) \
+ case a: \
+ if ((gfc_option.allow_std & d) == 0) \
+ continue; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_INTCST
+#define NAMED_REALCST(a,b,c,d) \
+ case a: \
+ if ((gfc_option.allow_std & d) == 0) \
+ continue; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_REALCST
+#define NAMED_CMPXCST(a,b,c,d) \
+ case a: \
+ if ((gfc_option.allow_std & d) == 0) \
+ continue; \
+ break;
+#include "iso-c-binding.def"
+#undef NAMED_CMPXCST
+ default:
+ ; /* Not GFC_STD_* versioned. */
+ }
+
+ switch (i)
+ {
#define NAMED_FUNCTION(a,b,c,d) \
- case a: \
- if ((gfc_option.allow_std & d) == 0) \
- continue; \
- create_intrinsic_function (b, (gfc_isym_id) c, \
- iso_c_module_name, \
- INTMOD_ISO_C_BINDING); \
+ case a: \
+ create_intrinsic_function (b, (gfc_isym_id) c, \
+ iso_c_module_name, \
+ INTMOD_ISO_C_BINDING); \
break;
#include "iso-c-binding.def"
#undef NAMED_FUNCTION
- default:
- generate_isocbinding_symbol (iso_c_module_name,
- (iso_c_binding_symbol) i, NULL);
- }
+ default:
+ generate_isocbinding_symbol (iso_c_module_name,
+ (iso_c_binding_symbol) i, NULL);
+ }
+ }
}
for (u = gfc_rename_list; u; u = u->next)
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 4c59bd59eeb..dcb11e85d1c 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -49,7 +49,7 @@ set_default_std_flags (void)
{
gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F95_DEL
| GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F95 | GFC_STD_F77
- | GFC_STD_F2008_OBS | GFC_STD_F2008_TR | GFC_STD_GNU | GFC_STD_LEGACY;
+ | GFC_STD_F2008_OBS | GFC_STD_F2008_TS | GFC_STD_GNU | GFC_STD_LEGACY;
gfc_option.warn_std = GFC_STD_F95_DEL | GFC_STD_LEGACY;
}
@@ -945,10 +945,10 @@ gfc_handle_option (size_t scode, const char *arg, int value,
gfc_option.warn_tabs = 0;
break;
- case OPT_std_f2008tr:
+ case OPT_std_f2008ts:
gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F77
| GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008 | GFC_STD_F2008_OBS
- | GFC_STD_F2008_TR;
+ | GFC_STD_F2008_TS;
gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS;
gfc_option.max_identifier_length = 63;
gfc_option.warn_ampersand = 1;
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index bccf7d49cf9..23dc0b66400 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -32,16 +32,20 @@ int matching_actual_arglist = 0;
/* Matches a kind-parameter expression, which is either a named
symbolic constant or a nonnegative integer constant. If
- successful, sets the kind value to the correct integer. */
+ successful, sets the kind value to the correct integer.
+ The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
+ symbol like e.g. 'c_int'. */
static match
-match_kind_param (int *kind)
+match_kind_param (int *kind, int *is_iso_c)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
gfc_symbol *sym;
const char *p;
match m;
+ *is_iso_c = 0;
+
m = gfc_match_small_literal_int (kind, NULL);
if (m != MATCH_NO)
return m;
@@ -56,6 +60,8 @@ match_kind_param (int *kind)
if (sym == NULL)
return MATCH_NO;
+ *is_iso_c = sym->attr.is_iso_c;
+
if (sym->attr.flavor != FL_PARAMETER)
return MATCH_NO;
@@ -77,20 +83,24 @@ match_kind_param (int *kind)
/* Get a trailing kind-specification for non-character variables.
Returns:
- the integer kind value or:
- -1 if an error was generated
- -2 if no kind was found */
+ * the integer kind value or
+ * -1 if an error was generated,
+ * -2 if no kind was found.
+ The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
+ symbol like e.g. 'c_int'. */
static int
-get_kind (void)
+get_kind (int *is_iso_c)
{
int kind;
match m;
+ *is_iso_c = 0;
+
if (gfc_match_char ('_') != MATCH_YES)
return -2;
- m = match_kind_param (&kind);
+ m = match_kind_param (&kind, is_iso_c);
if (m == MATCH_NO)
gfc_error ("Missing kind-parameter at %C");
@@ -188,7 +198,7 @@ match_digits (int signflag, int radix, char *buffer)
static match
match_integer_constant (gfc_expr **result, int signflag)
{
- int length, kind;
+ int length, kind, is_iso_c;
locus old_loc;
char *buffer;
gfc_expr *e;
@@ -208,7 +218,7 @@ match_integer_constant (gfc_expr **result, int signflag)
match_digits (signflag, 10, buffer);
- kind = get_kind ();
+ kind = get_kind (&is_iso_c);
if (kind == -2)
kind = gfc_default_integer_kind;
if (kind == -1)
@@ -221,6 +231,7 @@ match_integer_constant (gfc_expr **result, int signflag)
}
e = gfc_convert_integer (buffer, kind, 10, &gfc_current_locus);
+ e->ts.is_c_interop = is_iso_c;
if (gfc_range_check (e) != ARITH_OK)
{
@@ -473,7 +484,7 @@ backup:
static match
match_real_constant (gfc_expr **result, int signflag)
{
- int kind, count, seen_dp, seen_digits;
+ int kind, count, seen_dp, seen_digits, is_iso_c;
locus old_loc, temp_loc;
char *p, *buffer, c, exp_char;
gfc_expr *e;
@@ -611,7 +622,7 @@ done:
c = gfc_next_ascii_char ();
}
- kind = get_kind ();
+ kind = get_kind (&is_iso_c);
if (kind == -1)
goto cleanup;
@@ -665,6 +676,7 @@ done:
e = gfc_convert_real (buffer, kind, &gfc_current_locus);
if (negate)
mpfr_neg (e->value.real, e->value.real, GFC_RND_MODE);
+ e->ts.is_c_interop = is_iso_c;
switch (gfc_range_check (e))
{
@@ -1099,13 +1111,13 @@ static match
match_logical_constant (gfc_expr **result)
{
gfc_expr *e;
- int i, kind;
+ int i, kind, is_iso_c;
i = match_logical_constant_string ();
if (i == -1)
return MATCH_NO;
- kind = get_kind ();
+ kind = get_kind (&is_iso_c);
if (kind == -1)
return MATCH_ERROR;
if (kind == -2)
@@ -1118,6 +1130,7 @@ match_logical_constant (gfc_expr **result)
}
e = gfc_get_logical_expr (kind, &gfc_current_locus, i);
+ e->ts.is_c_interop = is_iso_c;
*result = e;
return MATCH_YES;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 84db3ddb019..0d7e03056b9 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -269,50 +269,18 @@ resolve_formal_arglist (gfc_symbol *proc)
if (sym->attr.if_source != IFSRC_UNKNOWN)
resolve_formal_arglist (sym);
- /* F08:C1279. */
- if (gfc_pure (proc)
- && sym->attr.flavor == FL_PROCEDURE && !gfc_pure (sym))
+ if (sym->attr.subroutine || sym->attr.external)
{
- gfc_error ("Dummy procedure '%s' of PURE procedure at %L must "
- "also be PURE", sym->name, &sym->declared_at);
- continue;
+ if (sym->attr.flavor == FL_UNKNOWN)
+ gfc_add_flavor (&sym->attr, FL_PROCEDURE, sym->name, &sym->declared_at);
}
-
- if (sym->attr.subroutine || sym->attr.external || sym->attr.intrinsic)
+ else
{
- if (proc->attr.implicit_pure && !gfc_pure(sym))
- proc->attr.implicit_pure = 0;
-
- /* F08:C1289. */
- if (gfc_elemental (proc))
- {
- gfc_error ("Dummy procedure at %L not allowed in ELEMENTAL "
- "procedure", &sym->declared_at);
- continue;
- }
-
- if (sym->attr.function
- && sym->ts.type == BT_UNKNOWN
- && sym->attr.intrinsic)
- {
- gfc_intrinsic_sym *isym;
- isym = gfc_find_function (sym->name);
- if (isym == NULL || !isym->specific)
- {
- gfc_error ("Unable to find a specific INTRINSIC procedure "
- "for the reference '%s' at %L", sym->name,
- &sym->declared_at);
- }
- sym->ts = isym->ts;
- }
-
- continue;
+ if (sym->ts.type == BT_UNKNOWN && !proc->attr.intrinsic
+ && (!sym->attr.function || sym->result == sym))
+ gfc_set_default_type (sym, 1, sym->ns);
}
- if (sym->ts.type == BT_UNKNOWN && !proc->attr.intrinsic
- && (!sym->attr.function || sym->result == sym))
- gfc_set_default_type (sym, 1, sym->ns);
-
gfc_resolve_array_spec (sym->as, 0);
/* We can't tell if an array with dimension (:) is assumed or deferred
@@ -343,44 +311,64 @@ resolve_formal_arglist (gfc_symbol *proc)
if (sym->attr.flavor == FL_UNKNOWN)
gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, &sym->declared_at);
- if (gfc_pure (proc) && !sym->attr.pointer
- && sym->attr.flavor != FL_PROCEDURE)
+ if (gfc_pure (proc))
{
- if (proc->attr.function && sym->attr.intent != INTENT_IN)
+ if (sym->attr.flavor == FL_PROCEDURE)
{
- if (sym->attr.value)
- gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s' "
- "of pure function '%s' at %L with VALUE "
- "attribute but without INTENT(IN)", sym->name,
- proc->name, &sym->declared_at);
- else
- gfc_error ("Argument '%s' of pure function '%s' at %L must be "
- "INTENT(IN) or VALUE", sym->name, proc->name,
- &sym->declared_at);
+ /* F08:C1279. */
+ if (!gfc_pure (sym))
+ {
+ gfc_error ("Dummy procedure '%s' of PURE procedure at %L must "
+ "also be PURE", sym->name, &sym->declared_at);
+ continue;
+ }
}
-
- if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
+ else if (!sym->attr.pointer)
{
- if (sym->attr.value)
- gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s' "
- "of pure subroutine '%s' at %L with VALUE "
- "attribute but without INTENT", sym->name,
- proc->name, &sym->declared_at);
- else
- gfc_error ("Argument '%s' of pure subroutine '%s' at %L must "
- "have its INTENT specified or have the VALUE "
- "attribute", sym->name, proc->name, &sym->declared_at);
+ if (proc->attr.function && sym->attr.intent != INTENT_IN)
+ {
+ if (sym->attr.value)
+ gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s'"
+ " of pure function '%s' at %L with VALUE "
+ "attribute but without INTENT(IN)",
+ sym->name, proc->name, &sym->declared_at);
+ else
+ gfc_error ("Argument '%s' of pure function '%s' at %L must "
+ "be INTENT(IN) or VALUE", sym->name, proc->name,
+ &sym->declared_at);
+ }
+
+ if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
+ {
+ if (sym->attr.value)
+ gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s'"
+ " of pure subroutine '%s' at %L with VALUE "
+ "attribute but without INTENT", sym->name,
+ proc->name, &sym->declared_at);
+ else
+ gfc_error ("Argument '%s' of pure subroutine '%s' at %L "
+ "must have its INTENT specified or have the "
+ "VALUE attribute", sym->name, proc->name,
+ &sym->declared_at);
+ }
}
}
- if (proc->attr.implicit_pure && !sym->attr.pointer
- && sym->attr.flavor != FL_PROCEDURE)
+ if (proc->attr.implicit_pure)
{
- if (proc->attr.function && sym->attr.intent != INTENT_IN)
- proc->attr.implicit_pure = 0;
+ if (sym->attr.flavor == FL_PROCEDURE)
+ {
+ if (!gfc_pure(sym))
+ proc->attr.implicit_pure = 0;
+ }
+ else if (!sym->attr.pointer)
+ {
+ if (proc->attr.function && sym->attr.intent != INTENT_IN)
+ proc->attr.implicit_pure = 0;
- if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
- proc->attr.implicit_pure = 0;
+ if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
+ proc->attr.implicit_pure = 0;
+ }
}
if (gfc_elemental (proc))
@@ -2821,7 +2809,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
&(args->expr->where));
/* See if we have interoperable type and type param. */
- if (verify_c_interop (arg_ts) == SUCCESS
+ if (gfc_verify_c_interop (arg_ts) == SUCCESS
|| gfc_check_any_c_kind (arg_ts) == SUCCESS)
{
if (args_sym->attr.target == 1)
@@ -4396,14 +4384,6 @@ compare_spec_to_ref (gfc_array_ref *ar)
return FAILURE;
}
- if (as->corank && ar->codimen == 0)
- {
- int n;
- ar->codimen = as->corank;
- for (n = ar->dimen; n < ar->dimen + ar->codimen; n++)
- ar->dimen_type[n] = DIMEN_THIS_IMAGE;
- }
-
return SUCCESS;
}
@@ -4652,8 +4632,23 @@ resolve_array_ref (gfc_array_ref *ar)
}
}
- if (ar->type == AR_FULL && ar->as->rank == 0)
- ar->type = AR_ELEMENT;
+ if (ar->type == AR_FULL)
+ {
+ if (ar->as->rank == 0)
+ ar->type = AR_ELEMENT;
+
+ /* Make sure array is the same as array(:,:), this way
+ we don't need to special case all the time. */
+ ar->dimen = ar->as->rank;
+ for (i = 0; i < ar->dimen; i++)
+ {
+ ar->dimen_type[i] = DIMEN_RANGE;
+
+ gcc_assert (ar->start[i] == NULL);
+ gcc_assert (ar->end[i] == NULL);
+ gcc_assert (ar->stride[i] == NULL);
+ }
+ }
/* If the reference type is unknown, figure out what kind it is. */
@@ -4672,6 +4667,14 @@ resolve_array_ref (gfc_array_ref *ar)
if (!ar->as->cray_pointee && compare_spec_to_ref (ar) == FAILURE)
return FAILURE;
+ if (ar->as->corank && ar->codimen == 0)
+ {
+ int n;
+ ar->codimen = ar->as->corank;
+ for (n = ar->dimen; n < ar->dimen + ar->codimen; n++)
+ ar->dimen_type[n] = DIMEN_THIS_IMAGE;
+ }
+
return SUCCESS;
}
@@ -10541,7 +10544,7 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
{
/* Skip implicitly typed dummy args here. */
if (curr_arg->sym->attr.implicit_type == 0)
- if (verify_c_interop_param (curr_arg->sym) == FAILURE)
+ if (gfc_verify_c_interop_param (curr_arg->sym) == FAILURE)
/* If something is found to fail, record the fact so we
can mark the symbol for the procedure as not being
BIND(C) to try and prevent multiple errors being
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 13a9c5147c0..63689bb700c 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -3512,11 +3512,9 @@ simplify_cobound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind, int upper)
switch (ref->u.ar.type)
{
case AR_ELEMENT:
- if (ref->next == NULL)
+ if (ref->u.ar.as->corank > 0)
{
- gcc_assert (ref->u.ar.as->corank > 0
- && ref->u.ar.as->rank == 0);
- as = ref->u.ar.as;
+ gcc_assert (as == ref->u.ar.as);
goto done;
}
as = NULL;
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 46eccb46aba..587ad7cb3c9 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -3635,7 +3635,7 @@ verify_bind_c_derived_type (gfc_symbol *derived_sym)
else
{
/* Grab the typespec for the given component and test the kind. */
- is_c_interop = verify_c_interop (&(curr_comp->ts));
+ is_c_interop = gfc_verify_c_interop (&(curr_comp->ts));
if (is_c_interop != SUCCESS)
{
@@ -4336,8 +4336,8 @@ generate_isocbinding_symbol (const char *mod_name, iso_c_binding_symbol s,
{
#define NAMED_INTCST(a,b,c,d) case a :
-#define NAMED_REALCST(a,b,c) case a :
-#define NAMED_CMPXCST(a,b,c) case a :
+#define NAMED_REALCST(a,b,c,d) case a :
+#define NAMED_CMPXCST(a,b,c,d) case a :
#define NAMED_LOGCST(a,b,c) case a :
#define NAMED_CHARKNDCST(a,b,c) case a :
#include "iso-c-binding.def"
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 37cdeb560ee..3472804e4c6 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -526,7 +526,6 @@ gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
ss->expr = expr;
info = &ss->data.info;
info->dimen = dimen;
- info->codimen = 0;
for (i = 0; i < info->dimen; i++)
info->dim[i] = i;
@@ -641,7 +640,7 @@ gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
tree tmp;
if (as && as->type == AS_EXPLICIT)
- for (n = 0; n < se->loop->dimen + se->loop->codimen; n++)
+ for (n = 0; n < se->loop->dimen; n++)
{
dim = se->ss->data.info.dim[n];
gcc_assert (dim < as->rank);
@@ -655,22 +654,18 @@ gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
gfc_add_block_to_block (&se->post, &tmpse.post);
lower = fold_convert (gfc_array_index_type, tmpse.expr);
- if (se->loop->codimen == 0
- || n < se->loop->dimen + se->loop->codimen - 1)
- {
- /* ...and the upper bound. */
- gfc_init_se (&tmpse, NULL);
- gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
- gfc_add_block_to_block (&se->pre, &tmpse.pre);
- gfc_add_block_to_block (&se->post, &tmpse.post);
- upper = fold_convert (gfc_array_index_type, tmpse.expr);
-
- /* Set the upper bound of the loop to UPPER - LOWER. */
- tmp = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, upper, lower);
- tmp = gfc_evaluate_now (tmp, &se->pre);
- se->loop->to[n] = tmp;
- }
+ /* ...and the upper bound. */
+ gfc_init_se (&tmpse, NULL);
+ gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
+ gfc_add_block_to_block (&se->pre, &tmpse.pre);
+ gfc_add_block_to_block (&se->post, &tmpse.post);
+ upper = fold_convert (gfc_array_index_type, tmpse.expr);
+
+ /* Set the upper bound of the loop to UPPER - LOWER. */
+ tmp = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type, upper, lower);
+ tmp = gfc_evaluate_now (tmp, &se->pre);
+ se->loop->to[n] = tmp;
}
}
}
@@ -977,13 +972,6 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
size, tmp);
size = gfc_evaluate_now (size, pre);
}
- for (n = info->dimen; n < info->dimen + info->codimen; n++)
- {
- gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
- gfc_index_zero_node);
- if (n < info->dimen + info->codimen - 1)
- gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], loop->to[n]);
- }
/* Get the size of the array. */
@@ -1470,8 +1458,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
bound = build_int_cst (size_type_node, n * size);
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3,
- tmp, init, bound);
+ builtin_decl_explicit (BUILT_IN_MEMCPY),
+ 3, tmp, init, bound);
gfc_add_expr_to_block (&body, tmp);
*poffset = fold_build2_loc (input_location, PLUS_EXPR,
@@ -1876,7 +1864,7 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
info->data = gfc_build_addr_expr (NULL_TREE, tmp);
info->offset = gfc_index_zero_node;
- for (i = 0; i < info->dimen + info->codimen; i++)
+ for (i = 0; i < info->dimen; i++)
{
info->delta[i] = gfc_index_zero_node;
info->start[i] = gfc_index_zero_node;
@@ -2116,7 +2104,7 @@ gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
int n;
int dim;
- for (n = 0; n < loop->dimen + loop->codimen; n++)
+ for (n = 0; n < loop->dimen; n++)
{
dim = info->dim[n];
if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
@@ -2621,6 +2609,18 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
/* Temporary array or derived type component. */
gcc_assert (se->loop);
index = se->loop->loopvar[se->loop->order[i]];
+
+ /* Pointer functions can have stride[0] different from unity.
+ Use the stride returned by the function call and stored in
+ the descriptor for the temporary. */
+ if (se->ss && se->ss->type == GFC_SS_FUNCTION
+ && se->ss->expr
+ && se->ss->expr->symtree
+ && se->ss->expr->symtree->n.sym->result
+ && se->ss->expr->symtree->n.sym->result->attr.pointer)
+ stride = gfc_conv_descriptor_stride_get (info->descriptor,
+ gfc_rank_cst[dim]);
+
if (!integer_zerop (info->delta[dim]))
index = fold_build2_loc (input_location, PLUS_EXPR,
gfc_array_index_type, index, info->delta[dim]);
@@ -2948,7 +2948,7 @@ gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
gcc_assert (!loop->array_parameter);
- for (dim = loop->dimen + loop->codimen - 1; dim >= 0; dim--)
+ for (dim = loop->dimen - 1; dim >= 0; dim--)
{
n = loop->order[dim];
@@ -3102,7 +3102,7 @@ gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
pblock = body;
/* Generate the loops. */
- for (dim = 0; dim < loop->dimen + loop->codimen; dim++)
+ for (dim = 0; dim < loop->dimen; dim++)
{
n = loop->order[dim];
gfc_trans_scalarized_loop_end (loop, n, pblock);
@@ -3175,82 +3175,83 @@ gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
}
+/* Precalculate (either lower or upper) bound of an array section.
+ BLOCK: Block in which the (pre)calculation code will go.
+ BOUNDS[DIM]: Where the bound value will be stored once evaluated.
+ VALUES[DIM]: Specified bound (NULL <=> unspecified).
+ DESC: Array descriptor from which the bound will be picked if unspecified
+ (either lower or upper bound according to LBOUND). */
+
+static void
+evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
+ tree desc, int dim, bool lbound)
+{
+ gfc_se se;
+ gfc_expr * input_val = values[dim];
+ tree *output = &bounds[dim];
+
+
+ if (input_val)
+ {
+ /* Specified section bound. */
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
+ gfc_add_block_to_block (block, &se.pre);
+ *output = se.expr;
+ }
+ else
+ {
+ /* No specific bound specified so use the bound of the array. */
+ *output = lbound ? gfc_conv_array_lbound (desc, dim) :
+ gfc_conv_array_ubound (desc, dim);
+ }
+ *output = gfc_evaluate_now (*output, block);
+}
+
+
/* Calculate the lower bound of an array section. */
static void
-gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim,
- bool coarray, bool coarray_last)
+gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
{
- gfc_expr *start;
- gfc_expr *end;
gfc_expr *stride = NULL;
tree desc;
gfc_se se;
gfc_ss_info *info;
+ gfc_array_ref *ar;
gcc_assert (ss->type == GFC_SS_SECTION);
info = &ss->data.info;
+ ar = &info->ref->u.ar;
- if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
+ if (ar->dimen_type[dim] == DIMEN_VECTOR)
{
/* We use a zero-based index to access the vector. */
info->start[dim] = gfc_index_zero_node;
info->end[dim] = NULL;
- if (!coarray)
- info->stride[dim] = gfc_index_one_node;
+ info->stride[dim] = gfc_index_one_node;
return;
}
- gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
+ gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
+ || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
desc = info->descriptor;
- start = info->ref->u.ar.start[dim];
- end = info->ref->u.ar.end[dim];
- if (!coarray)
- stride = info->ref->u.ar.stride[dim];
+ stride = ar->stride[dim];
/* Calculate the start of the range. For vector subscripts this will
be the range of the vector. */
- if (start)
- {
- /* Specified section start. */
- gfc_init_se (&se, NULL);
- gfc_conv_expr_type (&se, start, gfc_array_index_type);
- gfc_add_block_to_block (&loop->pre, &se.pre);
- info->start[dim] = se.expr;
- }
- else
- {
- /* No lower bound specified so use the bound of the array. */
- info->start[dim] = gfc_conv_array_lbound (desc, dim);
- }
- info->start[dim] = gfc_evaluate_now (info->start[dim], &loop->pre);
+ evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true);
/* Similarly calculate the end. Although this is not used in the
scalarizer, it is needed when checking bounds and where the end
is an expression with side-effects. */
- if (!coarray_last)
- {
- if (end)
- {
- /* Specified section start. */
- gfc_init_se (&se, NULL);
- gfc_conv_expr_type (&se, end, gfc_array_index_type);
- gfc_add_block_to_block (&loop->pre, &se.pre);
- info->end[dim] = se.expr;
- }
- else
- {
- /* No upper bound specified so use the bound of the array. */
- info->end[dim] = gfc_conv_array_ubound (desc, dim);
- }
- info->end[dim] = gfc_evaluate_now (info->end[dim], &loop->pre);
- }
+ evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false);
/* Calculate the stride. */
- if (!coarray && stride == NULL)
+ if (stride == NULL)
info->stride[dim] = gfc_index_one_node;
- else if (!coarray)
+ else
{
gfc_init_se (&se, NULL);
gfc_conv_expr_type (&se, stride, gfc_array_index_type);
@@ -3274,8 +3275,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
loop->dimen = 0;
/* Determine the rank of the loop. */
- for (ss = loop->ss;
- ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
+ for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
{
switch (ss->type)
{
@@ -3284,8 +3284,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
case GFC_SS_FUNCTION:
case GFC_SS_COMPONENT:
loop->dimen = ss->data.info.dimen;
- loop->codimen = ss->data.info.codimen;
- break;
+ goto done;
/* As usual, lbound and ubound are exceptions!. */
case GFC_SS_INTRINSIC:
@@ -3293,16 +3292,11 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
{
case GFC_ISYM_LBOUND:
case GFC_ISYM_UBOUND:
- loop->dimen = ss->data.info.dimen;
- loop->codimen = 0;
- break;
-
case GFC_ISYM_LCOBOUND:
case GFC_ISYM_UCOBOUND:
case GFC_ISYM_THIS_IMAGE:
loop->dimen = ss->data.info.dimen;
- loop->codimen = ss->data.info.codimen;
- break;
+ goto done;
default:
break;
@@ -3315,8 +3309,9 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
/* We should have determined the rank of the expression by now. If
not, that's bad news. */
- gcc_assert (loop->dimen + loop->codimen != 0);
+ gcc_unreachable ();
+done:
/* Loop over all the SS in the chain. */
for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
{
@@ -3330,14 +3325,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
for (n = 0; n < ss->data.info.dimen; n++)
- gfc_conv_section_startstride (loop, ss, ss->data.info.dim[n],
- false, false);
- for (n = ss->data.info.dimen;
- n < ss->data.info.dimen + ss->data.info.codimen; n++)
- gfc_conv_section_startstride (loop, ss, ss->data.info.dim[n], true,
- n == ss->data.info.dimen
- + ss->data.info.codimen -1);
-
+ gfc_conv_section_startstride (loop, ss, ss->data.info.dim[n]);
break;
case GFC_SS_INTRINSIC:
@@ -3856,7 +3844,6 @@ temporary:
base_type = gfc_get_element_type (base_type);
loop->temp_ss = gfc_get_temp_ss (base_type, dest->string_length,
loop->dimen);
- loop->temp_ss->data.temp.codimen = loop->codimen;
gfc_add_ss_to_loop (loop, loop->temp_ss);
}
else
@@ -3884,7 +3871,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
mpz_t i;
mpz_init (i);
- for (n = 0; n < loop->dimen + loop->codimen; n++)
+ for (n = 0; n < loop->dimen; n++)
{
loopspec[n] = NULL;
dynamic[n] = false;
@@ -3993,7 +3980,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
/* Set the extents of this range. */
cshape = loopspec[n]->shape;
- if (n < loop->dimen && cshape && INTEGER_CST_P (info->start[dim])
+ if (cshape && INTEGER_CST_P (info->start[dim])
&& INTEGER_CST_P (info->stride[dim]))
{
loop->from[n] = info->start[dim];
@@ -5915,7 +5902,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
se->string_length = loop.temp_ss->string_length;
gcc_assert (loop.temp_ss->data.temp.dimen == loop.dimen);
- loop.temp_ss->data.temp.codimen = loop.codimen;
gfc_add_ss_to_loop (&loop, loop.temp_ss);
}
@@ -5988,6 +5974,35 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
tree to;
tree base;
+ ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
+
+ if (se->want_coarray)
+ {
+ gfc_array_ref *ar = &info->ref->u.ar;
+
+ codim = gfc_get_corank (expr);
+ for (n = 0; n < codim - 1; n++)
+ {
+ /* Make sure we are not lost somehow. */
+ gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
+
+ /* Make sure the call to gfc_conv_section_startstride won't
+ generate unnecessary code to calculate stride. */
+ gcc_assert (ar->stride[n + ndim] == NULL);
+
+ gfc_conv_section_startstride (&loop, ss, n + ndim);
+ loop.from[n + loop.dimen] = info->start[n + ndim];
+ loop.to[n + loop.dimen] = info->end[n + ndim];
+ }
+
+ gcc_assert (n == codim - 1);
+ evaluate_bound (&loop.pre, info->start, ar->start,
+ info->descriptor, n + ndim, true);
+ loop.from[n + loop.dimen] = info->start[n + ndim];
+ }
+ else
+ codim = 0;
+
/* Set the string_length for a character array. */
if (expr->ts.type == BT_CHARACTER)
se->string_length = gfc_get_expr_charlen (expr);
@@ -6003,9 +6018,8 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
{
/* Otherwise make a new one. */
parmtype = gfc_get_element_type (TREE_TYPE (desc));
- parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
- loop.codimen, loop.from,
- loop.to, 0,
+ parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
+ loop.from, loop.to, 0,
GFC_ARRAY_UNKNOWN, false);
parm = gfc_create_var (parmtype, "parm");
}
@@ -6035,8 +6049,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
else
base = NULL_TREE;
- ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
- codim = info->codimen;
for (n = 0; n < ndim; n++)
{
stride = gfc_conv_array_stride (desc, n);
@@ -6138,24 +6150,15 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
gfc_rank_cst[dim], stride);
}
- for (n = ndim; n < ndim + codim; n++)
+ for (n = loop.dimen; n < loop.dimen + codim; n++)
{
- /* look for the corresponding scalarizer dimension: dim. */
- for (dim = 0; dim < ndim + codim; dim++)
- if (info->dim[dim] == n)
- break;
-
- /* loop exited early: the DIM being looked for has been found. */
- gcc_assert (dim < ndim + codim);
-
- from = loop.from[dim];
- to = loop.to[dim];
+ from = loop.from[n];
+ to = loop.to[n];
gfc_conv_descriptor_lbound_set (&loop.pre, parm,
- gfc_rank_cst[dim], from);
- if (n < ndim + codim - 1)
+ gfc_rank_cst[n], from);
+ if (n < loop.dimen + codim - 1)
gfc_conv_descriptor_ubound_set (&loop.pre, parm,
- gfc_rank_cst[dim], to);
- dim++;
+ gfc_rank_cst[n], to);
}
if (se->data_not_needed)
@@ -6632,7 +6635,7 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank,
gfc_add_expr_to_block (&block, tmp);
}
- tmp = built_in_decls[BUILT_IN_MEMCPY];
+ tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
tmp = build_call_expr_loc (input_location, tmp, 3,
dest, src, size);
}
@@ -6656,7 +6659,7 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank,
/* We know the temporary and the value will be the same length,
so can use memcpy. */
- tmp = built_in_decls[BUILT_IN_MEMCPY];
+ tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
tmp = build_call_expr_loc (input_location,
tmp, 3, gfc_conv_descriptor_data_get (dest),
gfc_conv_descriptor_data_get (src), size);
@@ -7412,7 +7415,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
in the array reference - (*desc.data)[<element>]. */
gfc_init_block (&realloc_block);
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_REALLOC], 2,
+ builtin_decl_explicit (BUILT_IN_REALLOC), 2,
fold_convert (pvoid_type_node, array1),
size2);
gfc_conv_descriptor_data_set (&realloc_block,
@@ -7428,8 +7431,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
/* Malloc expression. */
gfc_init_block (&alloc_block);
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MALLOC], 1,
- size2);
+ builtin_decl_explicit (BUILT_IN_MALLOC),
+ 1, size2);
gfc_conv_descriptor_data_set (&alloc_block,
desc, tmp);
tmp = gfc_conv_descriptor_dtype (desc);
@@ -7600,14 +7603,22 @@ static gfc_ss *
gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
{
gfc_ref *ref;
- gfc_array_ref *ar;
- gfc_ss *newss;
- int n;
for (ref = expr->ref; ref; ref = ref->next)
if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
break;
+ return gfc_walk_array_ref (ss, expr, ref);
+}
+
+
+gfc_ss *
+gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
+{
+ gfc_array_ref *ar;
+ gfc_ss *newss;
+ int n;
+
for (; ref; ref = ref->next)
{
if (ref->type == REF_SUBSTRING)
@@ -7622,12 +7633,6 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
ar = &ref->u.ar;
- if (ar->as->rank == 0 && ref->next != NULL)
- {
- /* Scalar coarray. */
- continue;
- }
-
switch (ar->type)
{
case AR_ELEMENT:
@@ -7642,7 +7647,6 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
/* Make sure array is the same as array(:,:), this way
we don't need to special case all the time. */
ar->dimen = ar->as->rank;
- ar->codimen = 0;
for (n = 0; n < ar->dimen; n++)
{
ar->dimen_type[n] = DIMEN_RANGE;
@@ -7651,14 +7655,6 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
gcc_assert (ar->end[n] == NULL);
gcc_assert (ar->stride[n] == NULL);
}
- for (n = ar->dimen; n < ar->dimen + ar->as->corank; n++)
- {
- newss->data.info.dim[n] = n;
- ar->dimen_type[n] = DIMEN_RANGE;
-
- gcc_assert (ar->start[n] == NULL);
- gcc_assert (ar->end[n] == NULL);
- }
ss = newss;
break;
@@ -7667,14 +7663,12 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
newss->data.info.ref = ref;
/* We add SS chains for all the subscripts in the section. */
- for (n = 0; n < ar->dimen + ar->codimen; n++)
+ for (n = 0; n < ar->dimen; n++)
{
gfc_ss *indexss;
switch (ar->dimen_type[n])
{
- case DIMEN_THIS_IMAGE:
- continue;
case DIMEN_ELEMENT:
/* Add SS for elemental (scalar) subscripts. */
gcc_assert (ar->start[n]);
@@ -7686,10 +7680,8 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
case DIMEN_RANGE:
/* We don't add anything for sections, just remember this
dimension for later. */
- newss->data.info.dim[newss->data.info.dimen
- + newss->data.info.codimen] = n;
- if (n < ar->dimen)
- newss->data.info.dimen++;
+ newss->data.info.dim[newss->data.info.dimen] = n;
+ newss->data.info.dimen++;
break;
case DIMEN_VECTOR:
@@ -7699,10 +7691,8 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
1, GFC_SS_VECTOR);
indexss->loop_chain = gfc_ss_terminator;
newss->data.info.subscript[n] = indexss;
- newss->data.info.dim[newss->data.info.dimen
- + newss->data.info.codimen] = n;
- if (n < ar->dimen)
- newss->data.info.dimen++;
+ newss->data.info.dim[newss->data.info.dimen] = n;
+ newss->data.info.dimen++;
break;
default:
@@ -7710,8 +7700,10 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
gcc_unreachable ();
}
}
- /* We should have at least one non-elemental dimension. */
- gcc_assert (newss->data.info.dimen > 0);
+ /* We should have at least one non-elemental dimension,
+ unless we are creating a descriptor for a (scalar) coarray. */
+ gcc_assert (newss->data.info.dimen > 0
+ || newss->data.info.ref->u.ar.as->corank > 0);
ss = newss;
break;
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 73d8c40c9e9..4d737bde94f 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -70,6 +70,8 @@ void gfc_trans_static_array_pointer (gfc_symbol *);
gfc_ss *gfc_walk_expr (gfc_expr *);
/* Workhorse for gfc_walk_expr. */
gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
+/* Workhorse for gfc_walk_variable_expr. */
+gfc_ss *gfc_walk_array_ref (gfc_ss *, gfc_expr *, gfc_ref * ref);
/* Walk the arguments of an elemental function. */
gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *,
gfc_ss_type);
diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c
index 21237c8d8ec..61ce44ba37a 100644
--- a/gcc/fortran/trans-common.c
+++ b/gcc/fortran/trans-common.c
@@ -1067,14 +1067,12 @@ translate_common (gfc_common_head *common, gfc_symbol *var_list)
HOST_WIDE_INT offset;
HOST_WIDE_INT current_offset;
unsigned HOST_WIDE_INT align;
- unsigned HOST_WIDE_INT max_align;
bool saw_equiv;
common_segment = NULL;
offset = 0;
current_offset = 0;
align = 1;
- max_align = 1;
saw_equiv = false;
/* Add symbols to the segment. */
@@ -1117,7 +1115,7 @@ translate_common (gfc_common_head *common, gfc_symbol *var_list)
if (gfc_option.flag_align_commons)
offset = align_segment (&align);
- if (offset & (max_align - 1))
+ if (offset)
{
/* The required offset conflicts with previous alignment
requirements. Insert padding immediately before this
@@ -1140,8 +1138,6 @@ translate_common (gfc_common_head *common, gfc_symbol *var_list)
/* Apply the offset to the new segments. */
apply_segment_offset (current_segment, offset);
current_offset += offset;
- if (max_align < align)
- max_align = align;
/* Add the new segments to the common block. */
common_segment = add_segments (common_segment, current_segment);
@@ -1161,11 +1157,11 @@ translate_common (gfc_common_head *common, gfc_symbol *var_list)
if (common_segment->offset != 0 && gfc_option.warn_align_commons)
{
if (strcmp (common->name, BLANK_COMMON_NAME))
- gfc_warning ("COMMON '%s' at %L requires %d bytes of padding at start; "
+ gfc_warning ("COMMON '%s' at %L requires %d bytes of padding; "
"reorder elements or use -fno-align-commons",
common->name, &common->where, (int)common_segment->offset);
else
- gfc_warning ("COMMON at %L requires %d bytes of padding at start; "
+ gfc_warning ("COMMON at %L requires %d bytes of padding; "
"reorder elements or use -fno-align-commons",
&common->where, (int)common_segment->offset);
}
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 44363c298ae..b7460b779e2 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1179,7 +1179,10 @@ gfc_get_symbol_decl (gfc_symbol * sym)
{
gfc_component *c = CLASS_DATA (sym);
if (!c->ts.u.derived->backend_decl)
- gfc_find_derived_vtab (c->ts.u.derived);
+ {
+ gfc_find_derived_vtab (c->ts.u.derived);
+ gfc_get_derived_type (sym->ts.u.derived);
+ }
}
/* All deferred character length procedures need to retain the backend
@@ -4986,7 +4989,7 @@ create_main_function (tree fndecl)
{
/* Per F2008, 8.5.1 END of the main program implies a
SYNC MEMORY. */
- tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+ tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
tmp = build_call_expr_loc (input_location, tmp, 0);
gfc_add_expr_to_block (&body, tmp);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 131927ce2a6..09b98d03faf 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1124,22 +1124,22 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
switch (kind)
{
case 0:
- fndecl = built_in_decls[BUILT_IN_POWIF];
+ fndecl = builtin_decl_explicit (BUILT_IN_POWIF);
break;
case 1:
- fndecl = built_in_decls[BUILT_IN_POWI];
+ fndecl = builtin_decl_explicit (BUILT_IN_POWI);
break;
case 2:
- fndecl = built_in_decls[BUILT_IN_POWIL];
+ fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
break;
case 3:
/* Use the __builtin_powil() only if real(kind=16) is
actually the C long double type. */
if (!gfc_real16_is_float128)
- fndecl = built_in_decls[BUILT_IN_POWIL];
+ fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
break;
default:
@@ -3357,10 +3357,16 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
else
goto end_pointer_check;
+ tmp = parmse.expr;
+
+ /* If the argument is passed by value, we need to strip the
+ INDIRECT_REF. */
+ if (!POINTER_TYPE_P (TREE_TYPE (parmse.expr)))
+ tmp = gfc_build_addr_expr (NULL_TREE, tmp);
cond = fold_build2_loc (input_location, EQ_EXPR,
- boolean_type_node, parmse.expr,
- fold_convert (TREE_TYPE (parmse.expr),
+ boolean_type_node, tmp,
+ fold_convert (TREE_TYPE (tmp),
null_pointer_node));
}
@@ -3855,7 +3861,8 @@ fill_with_spaces (tree start, tree type, tree size)
/* For a simple char type, we can call memset(). */
if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
return build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMSET], 3, start,
+ builtin_decl_explicit (BUILT_IN_MEMSET),
+ 3, start,
build_int_cst (gfc_get_int_type (gfc_c_int_kind),
lang_hooks.to_target_charset (' ')),
size);
@@ -4015,13 +4022,13 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
cond2 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, slen,
dlen);
tmp2 = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMMOVE],
- 3, dest, src, dlen);
+ builtin_decl_explicit (BUILT_IN_MEMMOVE),
+ 3, dest, src, dlen);
/* Else copy and pad with spaces. */
tmp3 = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMMOVE],
- 3, dest, src, slen);
+ builtin_decl_explicit (BUILT_IN_MEMMOVE),
+ 3, dest, src, slen);
tmp4 = fold_build_pointer_plus_loc (input_location, dest, slen);
tmp4 = fill_with_spaces (tmp4, chartype,
@@ -5816,8 +5823,8 @@ gfc_trans_zero_assign (gfc_expr * expr)
/* Construct call to __builtin_memset. */
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMSET],
- 3, dest, integer_zero_node, len);
+ builtin_decl_explicit (BUILT_IN_MEMSET),
+ 3, dest, integer_zero_node, len);
return fold_convert (void_type_node, tmp);
}
@@ -5845,7 +5852,8 @@ gfc_build_memcpy_call (tree dst, tree src, tree len)
/* Construct call to __builtin_memcpy. */
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3, dst, src, len);
+ builtin_decl_explicit (BUILT_IN_MEMCPY),
+ 3, dst, src, len);
return fold_convert (void_type_node, tmp);
}
@@ -6056,8 +6064,8 @@ alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
}
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MALLOC], 1,
- size_in_bytes);
+ builtin_decl_explicit (BUILT_IN_MALLOC),
+ 1, size_in_bytes);
tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
gfc_add_modify (block, lse.expr, tmp);
if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
@@ -6083,8 +6091,8 @@ alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
build_empty_stmt (input_location));
gfc_add_expr_to_block (block, tmp);
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_REALLOC], 2,
- fold_convert (pvoid_type_node, lse.expr),
+ builtin_decl_explicit (BUILT_IN_REALLOC),
+ 2, fold_convert (pvoid_type_node, lse.expr),
size_in_bytes);
tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
gfc_add_modify (block, lse.expr, tmp);
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index de5a809c81a..83fc4fc52ef 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -139,7 +139,7 @@ static tree
builtin_decl_for_precision (enum built_in_function base_built_in,
int precision)
{
- int i = END_BUILTINS;
+ enum built_in_function i = END_BUILTINS;
gfc_intrinsic_map_t *m;
for (m = gfc_intrinsic_map; m->double_built_in != base_built_in ; m++)
@@ -158,7 +158,7 @@ builtin_decl_for_precision (enum built_in_function base_built_in,
return m->real16_decl;
}
- return (i == END_BUILTINS ? NULL_TREE : built_in_decls[i]);
+ return (i == END_BUILTINS ? NULL_TREE : builtin_decl_explicit (i));
}
@@ -679,26 +679,28 @@ gfc_build_intrinsic_lib_fndecls (void)
m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
{
if (m->float_built_in != END_BUILTINS)
- m->real4_decl = built_in_decls[m->float_built_in];
+ m->real4_decl = builtin_decl_explicit (m->float_built_in);
if (m->complex_float_built_in != END_BUILTINS)
- m->complex4_decl = built_in_decls[m->complex_float_built_in];
+ m->complex4_decl = builtin_decl_explicit (m->complex_float_built_in);
if (m->double_built_in != END_BUILTINS)
- m->real8_decl = built_in_decls[m->double_built_in];
+ m->real8_decl = builtin_decl_explicit (m->double_built_in);
if (m->complex_double_built_in != END_BUILTINS)
- m->complex8_decl = built_in_decls[m->complex_double_built_in];
+ m->complex8_decl = builtin_decl_explicit (m->complex_double_built_in);
/* If real(kind=10) exists, it is always long double. */
if (m->long_double_built_in != END_BUILTINS)
- m->real10_decl = built_in_decls[m->long_double_built_in];
+ m->real10_decl = builtin_decl_explicit (m->long_double_built_in);
if (m->complex_long_double_built_in != END_BUILTINS)
- m->complex10_decl = built_in_decls[m->complex_long_double_built_in];
+ m->complex10_decl
+ = builtin_decl_explicit (m->complex_long_double_built_in);
if (!gfc_real16_is_float128)
{
if (m->long_double_built_in != END_BUILTINS)
- m->real16_decl = built_in_decls[m->long_double_built_in];
+ m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
if (m->complex_long_double_built_in != END_BUILTINS)
- m->complex16_decl = built_in_decls[m->complex_long_double_built_in];
+ m->complex16_decl
+ = builtin_decl_explicit (m->complex_long_double_built_in);
}
else if (quad_decls[m->double_built_in] != NULL_TREE)
{
@@ -924,18 +926,37 @@ gfc_conv_intrinsic_exponent (gfc_se *se, gfc_expr *expr)
/* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
AR_FULL, suitable for the scalarizer. */
-static void
-convert_element_to_coarray_ref (gfc_expr *expr)
+static gfc_ss *
+walk_coarray (gfc_expr *e)
{
- gfc_ref *ref;
+ gfc_ss *ss;
- for (ref = expr->ref; ref; ref = ref->next)
- if (ref->type == REF_ARRAY && ref->next == NULL
- && ref->u.ar.codimen)
- {
- ref->u.ar.type = AR_FULL;
- break;
- }
+ gcc_assert (gfc_get_corank (e) > 0);
+
+ ss = gfc_walk_expr (e);
+
+ /* Fix scalar coarray. */
+ if (ss == gfc_ss_terminator)
+ {
+ gfc_ref *ref;
+
+ ref = e->ref;
+ while (ref)
+ {
+ if (ref->type == REF_ARRAY
+ && ref->u.ar.codimen > 0)
+ break;
+
+ ref = ref->next;
+ }
+
+ gcc_assert (ref != NULL);
+ if (ref->u.ar.type == AR_ELEMENT)
+ ref->u.ar.type = AR_SECTION;
+ ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
+ }
+
+ return ss;
}
@@ -969,11 +990,9 @@ trans_this_image (gfc_se * se, gfc_expr *expr)
/* Obtain the descriptor of the COARRAY. */
gfc_init_se (&argse, NULL);
- if (expr->value.function.actual->expr->rank == 0)
- convert_element_to_coarray_ref (expr->value.function.actual->expr);
- ss = gfc_walk_expr (expr->value.function.actual->expr);
+ ss = walk_coarray (expr->value.function.actual->expr);
gcc_assert (ss != gfc_ss_terminator);
- ss->data.info.codimen = corank;
+ argse.want_coarray = 1;
gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr, ss);
gfc_add_block_to_block (&se->pre, &argse.pre);
gfc_add_block_to_block (&se->post, &argse.post);
@@ -1156,11 +1175,9 @@ trans_image_index (gfc_se * se, gfc_expr *expr)
/* Obtain the descriptor of the COARRAY. */
gfc_init_se (&argse, NULL);
- if (expr->value.function.actual->expr->rank == 0)
- convert_element_to_coarray_ref (expr->value.function.actual->expr);
- ss = gfc_walk_expr (expr->value.function.actual->expr);
+ ss = walk_coarray (expr->value.function.actual->expr);
gcc_assert (ss != gfc_ss_terminator);
- ss->data.info.codimen = corank;
+ argse.want_coarray = 1;
gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr, ss);
gfc_add_block_to_block (&se->pre, &argse.pre);
gfc_add_block_to_block (&se->post, &argse.post);
@@ -1482,12 +1499,10 @@ conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
gcc_assert (arg->expr->expr_type == EXPR_VARIABLE);
corank = gfc_get_corank (arg->expr);
- if (expr->value.function.actual->expr->rank == 0)
- convert_element_to_coarray_ref (expr->value.function.actual->expr);
- ss = gfc_walk_expr (arg->expr);
+ ss = walk_coarray (arg->expr);
gcc_assert (ss != gfc_ss_terminator);
- ss->data.info.codimen = corank;
gfc_init_se (&argse, NULL);
+ argse.want_coarray = 1;
gfc_conv_expr_descriptor (&argse, arg->expr, ss);
gfc_add_block_to_block (&se->pre, &argse.pre);
@@ -2202,7 +2217,8 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, enum tree_code op)
if (FLOAT_TYPE_P (TREE_TYPE (mvar)))
{
isnan = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_ISNAN], 1, mvar);
+ builtin_decl_explicit (BUILT_IN_ISNAN),
+ 1, mvar);
tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
boolean_type_node, tmp,
fold_convert (boolean_type_node, isnan));
@@ -4079,17 +4095,17 @@ gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
if (argsize <= INT_TYPE_SIZE)
{
arg_type = unsigned_type_node;
- func = built_in_decls[BUILT_IN_CLZ];
+ func = builtin_decl_explicit (BUILT_IN_CLZ);
}
else if (argsize <= LONG_TYPE_SIZE)
{
arg_type = long_unsigned_type_node;
- func = built_in_decls[BUILT_IN_CLZL];
+ func = builtin_decl_explicit (BUILT_IN_CLZL);
}
else if (argsize <= LONG_LONG_TYPE_SIZE)
{
arg_type = long_long_unsigned_type_node;
- func = built_in_decls[BUILT_IN_CLZLL];
+ func = builtin_decl_explicit (BUILT_IN_CLZLL);
}
else
{
@@ -4128,7 +4144,7 @@ gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
where ULL_MAX is the largest value that a ULL_MAX can hold
(0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
is the bit-size of the long long type (64 in this example). */
- tree ullsize, ullmax, tmp1, tmp2;
+ tree ullsize, ullmax, tmp1, tmp2, btmp;
ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
@@ -4146,16 +4162,14 @@ gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
arg, ullsize);
tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
+ btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
tmp1 = fold_convert (result_type,
- build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_CLZLL],
- 1, tmp1));
+ build_call_expr_loc (input_location, btmp, 1, tmp1));
tmp2 = fold_convert (long_long_unsigned_type_node, arg);
+ btmp = builtin_decl_explicit (BUILT_IN_CLZLL);
tmp2 = fold_convert (result_type,
- build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_CLZLL],
- 1, tmp2));
+ build_call_expr_loc (input_location, btmp, 1, tmp2));
tmp2 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
tmp2, ullsize);
@@ -4198,17 +4212,17 @@ gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
if (argsize <= INT_TYPE_SIZE)
{
arg_type = unsigned_type_node;
- func = built_in_decls[BUILT_IN_CTZ];
+ func = builtin_decl_explicit (BUILT_IN_CTZ);
}
else if (argsize <= LONG_TYPE_SIZE)
{
arg_type = long_unsigned_type_node;
- func = built_in_decls[BUILT_IN_CTZL];
+ func = builtin_decl_explicit (BUILT_IN_CTZL);
}
else if (argsize <= LONG_LONG_TYPE_SIZE)
{
arg_type = long_long_unsigned_type_node;
- func = built_in_decls[BUILT_IN_CTZLL];
+ func = builtin_decl_explicit (BUILT_IN_CTZLL);
}
else
{
@@ -4242,7 +4256,7 @@ gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
where ULL_MAX is the largest value that a ULL_MAX can hold
(0xFFFFFFFFFFFFFFFF for a 64-bit long long type), and ULLSIZE
is the bit-size of the long long type (64 in this example). */
- tree ullsize, ullmax, tmp1, tmp2;
+ tree ullsize, ullmax, tmp1, tmp2, btmp;
ullsize = build_int_cst (result_type, LONG_LONG_TYPE_SIZE);
ullmax = fold_build1_loc (input_location, BIT_NOT_EXPR,
@@ -4257,18 +4271,16 @@ gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
tmp1 = fold_build2_loc (input_location, RSHIFT_EXPR, arg_type,
arg, ullsize);
tmp1 = fold_convert (long_long_unsigned_type_node, tmp1);
+ btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
tmp1 = fold_convert (result_type,
- build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_CTZLL],
- 1, tmp1));
+ build_call_expr_loc (input_location, btmp, 1, tmp1));
tmp1 = fold_build2_loc (input_location, PLUS_EXPR, result_type,
tmp1, ullsize);
tmp2 = fold_convert (long_long_unsigned_type_node, arg);
+ btmp = builtin_decl_explicit (BUILT_IN_CTZLL);
tmp2 = fold_convert (result_type,
- build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_CTZLL],
- 1, tmp2));
+ build_call_expr_loc (input_location, btmp, 1, tmp2));
trailz = fold_build3_loc (input_location, COND_EXPR, result_type,
cond, tmp1, tmp2);
@@ -4304,17 +4316,23 @@ gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
if (argsize <= INT_TYPE_SIZE)
{
arg_type = unsigned_type_node;
- func = built_in_decls[parity ? BUILT_IN_PARITY : BUILT_IN_POPCOUNT];
+ func = builtin_decl_explicit (parity
+ ? BUILT_IN_PARITY
+ : BUILT_IN_POPCOUNT);
}
else if (argsize <= LONG_TYPE_SIZE)
{
arg_type = long_unsigned_type_node;
- func = built_in_decls[parity ? BUILT_IN_PARITYL : BUILT_IN_POPCOUNTL];
+ func = builtin_decl_explicit (parity
+ ? BUILT_IN_PARITYL
+ : BUILT_IN_POPCOUNTL);
}
else if (argsize <= LONG_LONG_TYPE_SIZE)
{
arg_type = long_long_unsigned_type_node;
- func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
+ func = builtin_decl_explicit (parity
+ ? BUILT_IN_PARITYLL
+ : BUILT_IN_POPCOUNTLL);
}
else
{
@@ -4327,7 +4345,9 @@ gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity)
as 'long long'. */
gcc_assert (argsize == 2 * LONG_LONG_TYPE_SIZE);
- func = built_in_decls[parity ? BUILT_IN_PARITYLL : BUILT_IN_POPCOUNTLL];
+ func = builtin_decl_explicit (parity
+ ? BUILT_IN_PARITYLL
+ : BUILT_IN_POPCOUNTLL);
/* Convert it to an integer, and store into a variable. */
utype = gfc_build_uint_type (argsize);
@@ -4580,7 +4600,8 @@ gfc_conv_intrinsic_isnan (gfc_se * se, gfc_expr * expr)
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
se->expr = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_ISNAN], 1, arg);
+ builtin_decl_explicit (BUILT_IN_ISNAN),
+ 1, arg);
STRIP_TYPE_NOPS (se->expr);
se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
}
@@ -5490,7 +5511,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr)
/* Use memcpy to do the transfer. */
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY],
+ builtin_decl_explicit (BUILT_IN_MEMCPY),
3,
tmp,
fold_convert (pvoid_type_node, source),
@@ -5535,7 +5556,7 @@ scalar_transfer:
gfc_add_modify (&block, tmpdecl,
fold_convert (TREE_TYPE (ptr), tmp));
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3,
+ builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
fold_convert (pvoid_type_node, tmpdecl),
fold_convert (pvoid_type_node, ptr),
extent);
@@ -5560,7 +5581,7 @@ scalar_transfer:
/* Use memcpy to do the transfer. */
tmp = gfc_build_addr_expr (NULL_TREE, tmpdecl);
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3,
+ builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
fold_convert (pvoid_type_node, tmp),
fold_convert (pvoid_type_node, ptr),
extent);
@@ -6001,7 +6022,8 @@ gfc_conv_intrinsic_repeat (gfc_se * se, gfc_expr * expr)
tmp = fold_build_pointer_plus_loc (input_location,
fold_convert (pvoid_type_node, dest), tmp);
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMMOVE], 3, tmp, src,
+ builtin_decl_explicit (BUILT_IN_MEMMOVE),
+ 3, tmp, src,
fold_build2_loc (input_location, MULT_EXPR,
size_type_node, slen,
fold_convert (size_type_node,
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index cfe8612dfc9..a41e97bdadf 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -249,7 +249,8 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
gfc_conv_descriptor_data_set (&cond_block, dest, ptr);
call = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3, ptr,
+ builtin_decl_explicit (BUILT_IN_MEMCPY),
+ 3, ptr,
fold_convert (pvoid_type_node,
gfc_conv_descriptor_data_get (src)),
size);
@@ -300,7 +301,7 @@ gfc_omp_clause_assign_op (tree clause ATTRIBUTE_UNUSED, tree dest, tree src)
size, esize);
size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
call = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3,
+ builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
fold_convert (pvoid_type_node,
gfc_conv_descriptor_data_get (dest)),
fold_convert (pvoid_type_node,
@@ -1273,7 +1274,7 @@ gfc_trans_omp_atomic (gfc_code *code)
static tree
gfc_trans_omp_barrier (void)
{
- tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER];
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
return build_call_expr_loc (input_location, decl, 0);
}
@@ -1547,7 +1548,7 @@ gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
static tree
gfc_trans_omp_flush (void)
{
- tree decl = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+ tree decl = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
return build_call_expr_loc (input_location, decl, 0);
}
@@ -1738,14 +1739,14 @@ gfc_trans_omp_task (gfc_code *code)
static tree
gfc_trans_omp_taskwait (void)
{
- tree decl = built_in_decls [BUILT_IN_GOMP_TASKWAIT];
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
return build_call_expr_loc (input_location, decl, 0);
}
static tree
gfc_trans_omp_taskyield (void)
{
- tree decl = built_in_decls [BUILT_IN_GOMP_TASKYIELD];
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
return build_call_expr_loc (input_location, decl, 0);
}
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 8e43f4de1e7..c71eeec400f 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -602,7 +602,7 @@ gfc_trans_stop (gfc_code *code, bool error_stop)
if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
{
/* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
- tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+ tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
tmp = build_call_expr_loc (input_location, tmp, 0);
gfc_add_expr_to_block (&se.pre, tmp);
@@ -774,7 +774,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type)
image control statements SYNC IMAGES and SYNC ALL. */
if (gfc_option.coarray == GFC_FCOARRAY_LIB)
{
- tmp = built_in_decls [BUILT_IN_SYNC_SYNCHRONIZE];
+ tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
tmp = build_call_expr_loc (input_location, tmp, 0);
gfc_add_expr_to_block (&se.pre, tmp);
}
@@ -5076,7 +5076,7 @@ gfc_trans_allocate (gfc_code * code)
slen);
dlen = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3,
+ builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
@@ -5251,7 +5251,7 @@ gfc_trans_deallocate (gfc_code *code)
slen);
dlen = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MEMCPY], 3,
+ builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, astat,
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index aa8e43bd8b8..cb5f30e28e0 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -298,8 +298,8 @@ get_int_kind_from_minimal_width (int size)
/* Generate the CInteropKind_t objects for the C interoperable
kinds. */
-static
-void init_c_interop_kinds (void)
+void
+gfc_init_c_interop_kinds (void)
{
int i;
@@ -316,11 +316,11 @@ void init_c_interop_kinds (void)
strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
c_interop_kinds_table[a].f90_type = BT_INTEGER; \
c_interop_kinds_table[a].value = c;
-#define NAMED_REALCST(a,b,c) \
+#define NAMED_REALCST(a,b,c,d) \
strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
c_interop_kinds_table[a].f90_type = BT_REAL; \
c_interop_kinds_table[a].value = c;
-#define NAMED_CMPXCST(a,b,c) \
+#define NAMED_CMPXCST(a,b,c,d) \
strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \
c_interop_kinds_table[a].f90_type = BT_COMPLEX; \
c_interop_kinds_table[a].value = c;
@@ -584,11 +584,9 @@ gfc_init_kinds (void)
/* Choose atomic kinds to match C's int. */
gfc_atomic_int_kind = gfc_c_int_kind;
gfc_atomic_logical_kind = gfc_c_int_kind;
-
- /* initialize the C interoperable kinds */
- init_c_interop_kinds();
}
+
/* Make sure that a valid kind is present. Returns an index into the
associated kinds array, -1 if the kind is not present. */
@@ -1256,7 +1254,7 @@ gfc_build_array_type (tree type, gfc_array_spec * as,
for (n = as->rank; n < as->rank + as->corank; n++)
{
- if (as->lower[n] == NULL)
+ if (as->type != AS_DEFERRED && as->lower[n] == NULL)
lbound[n] = gfc_index_one_node;
else
lbound[n] = gfc_conv_array_bound (as->lower[n]);
diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h
index 57afd8caef9..2ab94b3f184 100644
--- a/gcc/fortran/trans-types.h
+++ b/gcc/fortran/trans-types.h
@@ -58,6 +58,7 @@ void gfc_convert_function_code (gfc_namespace *);
/* trans-types.c */
void gfc_init_kinds (void);
void gfc_init_types (void);
+void gfc_init_c_interop_kinds (void);
tree gfc_get_int_type (int);
tree gfc_get_real_type (int);
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 764bdf42e45..88bd389c545 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -323,7 +323,14 @@ gfc_build_array_ref (tree base, tree offset, tree decl)
return fold_convert (TYPE_MAIN_VARIANT (type), base);
}
- gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+ /* Scalar coarray, there is nothing to do. */
+ if (TREE_CODE (type) != ARRAY_TYPE)
+ {
+ gcc_assert (decl == NULL_TREE);
+ gcc_assert (integer_zerop (offset));
+ return base;
+ }
+
type = TREE_TYPE (type);
if (DECL_P (base))
@@ -512,7 +519,7 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock,
tree
gfc_call_malloc (stmtblock_t * block, tree type, tree size)
{
- tree tmp, msg, malloc_result, null_result, res;
+ tree tmp, msg, malloc_result, null_result, res, malloc_tree;
stmtblock_t block2;
size = gfc_evaluate_now (size, block);
@@ -529,10 +536,11 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size)
size = fold_build2_loc (input_location, MAX_EXPR, size_type_node, size,
build_int_cst (size_type_node, 1));
+ malloc_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
gfc_add_modify (&block2, res,
fold_convert (prvoid_type_node,
build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MALLOC], 1, size)));
+ malloc_tree, 1, size)));
/* Optionally check whether malloc was successful. */
if (gfc_option.rtcheck & GFC_RTCHECK_MEM)
@@ -604,7 +612,7 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
gfc_add_modify (block, pointer,
fold_convert (TREE_TYPE (pointer),
build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_MALLOC], 1,
+ builtin_decl_explicit (BUILT_IN_MALLOC), 1,
fold_build2_loc (input_location,
MAX_EXPR, size_type_node, size,
build_int_cst (size_type_node, 1)))));
@@ -783,7 +791,8 @@ gfc_call_free (tree var)
cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, var,
build_int_cst (pvoid_type_node, 0));
call = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_FREE], 1, var);
+ builtin_decl_explicit (BUILT_IN_FREE),
+ 1, var);
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, call,
build_empty_stmt (input_location));
gfc_add_expr_to_block (&block, tmp);
@@ -871,8 +880,8 @@ gfc_deallocate_with_status (tree pointer, tree status, bool can_fail,
/* When POINTER is not NULL, we free it. */
gfc_start_block (&non_null);
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_FREE], 1,
- fold_convert (pvoid_type_node, pointer));
+ builtin_decl_explicit (BUILT_IN_FREE), 1,
+ fold_convert (pvoid_type_node, pointer));
gfc_add_expr_to_block (&non_null, tmp);
if (status != NULL_TREE && !integer_zerop (status))
@@ -968,8 +977,8 @@ gfc_deallocate_scalar_with_status (tree pointer, tree status, bool can_fail,
}
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_FREE], 1,
- fold_convert (pvoid_type_node, pointer));
+ builtin_decl_explicit (BUILT_IN_FREE), 1,
+ fold_convert (pvoid_type_node, pointer));
gfc_add_expr_to_block (&non_null, tmp);
if (status != NULL_TREE && !integer_zerop (status))
@@ -1026,7 +1035,7 @@ gfc_call_realloc (stmtblock_t * block, tree mem, tree size)
/* Call realloc and check the result. */
tmp = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_REALLOC], 2,
+ builtin_decl_explicit (BUILT_IN_REALLOC), 2,
fold_convert (pvoid_type_node, mem), size);
gfc_add_modify (block, res, fold_convert (type, tmp));
null_result = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
@@ -1593,7 +1602,8 @@ gfc_unlikely (tree cond)
cond = fold_convert (long_integer_type_node, cond);
tmp = build_zero_cst (long_integer_type_node);
cond = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
+ builtin_decl_explicit (BUILT_IN_EXPECT),
+ 2, cond, tmp);
cond = fold_convert (boolean_type_node, cond);
return cond;
}
@@ -1609,7 +1619,8 @@ gfc_likely (tree cond)
cond = fold_convert (long_integer_type_node, cond);
tmp = build_one_cst (long_integer_type_node);
cond = build_call_expr_loc (input_location,
- built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
+ builtin_decl_explicit (BUILT_IN_EXPECT),
+ 2, cond, tmp);
cond = fold_convert (boolean_type_node, cond);
return cond;
}
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 0c249a6736a..535c207fcd4 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -86,6 +86,8 @@ typedef struct gfc_se
args alias. */
unsigned force_tmp:1;
+ unsigned want_coarray:1;
+
/* Scalarization parameters. */
struct gfc_se *parent;
struct gfc_ss *ss;
@@ -116,7 +118,7 @@ gfc_coarray_type;
typedef struct gfc_ss_info
{
- int dimen, codimen;
+ int dimen;
/* The ref that holds information on this section. */
gfc_ref *ref;
/* The descriptor of this array. */
@@ -210,7 +212,7 @@ typedef struct gfc_ss
{
/* The rank of the temporary. May be less than the rank of the
assigned expression. */
- int dimen, codimen;
+ int dimen;
tree type;
}
temp;
@@ -243,7 +245,7 @@ typedef struct gfc_loopinfo
stmtblock_t pre;
stmtblock_t post;
- int dimen, codimen;
+ int dimen;
/* All the SS involved with this loop. */
gfc_ss *ss;
diff --git a/gcc/function.c b/gcc/function.c
index 27fe70328c6..dc1684a6128 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -147,9 +147,6 @@ extern tree debug_find_var_in_block_tree (tree, tree);
can always export `prologue_epilogue_contains'. */
static void record_insns (rtx, rtx, htab_t *) ATTRIBUTE_UNUSED;
static bool contains (const_rtx, htab_t);
-#ifdef HAVE_return
-static void emit_return_into_block (basic_block);
-#endif
static void prepare_function_start (void);
static void do_clobber_return_reg (rtx, void *);
static void do_use_return_reg (rtx, void *);
@@ -3620,7 +3617,7 @@ gimplify_parameters (void)
&& compare_tree_int (DECL_SIZE_UNIT (parm),
STACK_CHECK_MAX_VAR_SIZE) > 0))
{
- local = create_tmp_reg (type, get_name (parm));
+ local = create_tmp_var (type, get_name (parm));
DECL_IGNORED_P (local) = 0;
/* If PARM was addressable, move that flag over
to the local copy, as its address will be taken,
@@ -3628,6 +3625,9 @@ gimplify_parameters (void)
as we'll query that flag during gimplification. */
if (TREE_ADDRESSABLE (parm))
TREE_ADDRESSABLE (local) = 1;
+ else if (TREE_CODE (type) == COMPLEX_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE)
+ DECL_GIMPLE_REG_P (local) = 1;
}
else
{
@@ -3638,8 +3638,10 @@ gimplify_parameters (void)
DECL_IGNORED_P (addr) = 0;
local = build_fold_indirect_ref (addr);
- t = built_in_decls[BUILT_IN_ALLOCA];
- t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm));
+ t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+ t = build_call_expr (t, 2, DECL_SIZE_UNIT (parm),
+ size_int (DECL_ALIGN (parm)));
+
/* The call has been built for a variable-sized object. */
CALL_ALLOCA_FOR_VAR_P (t) = 1;
t = fold_convert (ptr_type, t);
@@ -5285,6 +5287,203 @@ prologue_epilogue_contains (const_rtx insn)
return 0;
}
+#ifdef HAVE_simple_return
+
+/* A for_each_rtx subroutine of record_hard_reg_sets. */
+static int
+record_hard_reg_uses_1 (rtx *px, void *data)
+{
+ rtx x = *px;
+ HARD_REG_SET *pused = (HARD_REG_SET *)data;
+
+ if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ add_to_hard_reg_set (pused, GET_MODE (x), REGNO (x));
+ return 0;
+}
+
+/* Like record_hard_reg_sets, but called through note_uses. */
+static void
+record_hard_reg_uses (rtx *px, void *data)
+{
+ for_each_rtx (px, record_hard_reg_uses_1, data);
+}
+
+/* Return true if INSN requires the stack frame to be set up.
+ PROLOGUE_USED contains the hard registers used in the function
+ prologue. SET_UP_BY_PROLOGUE is the set of registers we expect the
+ prologue to set up for the function. */
+static bool
+requires_stack_frame_p (rtx insn, HARD_REG_SET prologue_used,
+ HARD_REG_SET set_up_by_prologue)
+{
+ df_ref *df_rec;
+ HARD_REG_SET hardregs;
+ unsigned regno;
+
+ if (!INSN_P (insn) || DEBUG_INSN_P (insn))
+ return false;
+ if (CALL_P (insn))
+ return !SIBLING_CALL_P (insn);
+
+ CLEAR_HARD_REG_SET (hardregs);
+ for (df_rec = DF_INSN_DEFS (insn); *df_rec; df_rec++)
+ {
+ rtx dreg = DF_REF_REG (*df_rec);
+
+ if (!REG_P (dreg))
+ continue;
+
+ add_to_hard_reg_set (&hardregs, GET_MODE (dreg),
+ REGNO (dreg));
+ }
+ if (hard_reg_set_intersect_p (hardregs, prologue_used))
+ return true;
+ AND_COMPL_HARD_REG_SET (hardregs, call_used_reg_set);
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (hardregs, regno)
+ && df_regs_ever_live_p (regno))
+ return true;
+
+ for (df_rec = DF_INSN_USES (insn); *df_rec; df_rec++)
+ {
+ rtx reg = DF_REF_REG (*df_rec);
+
+ if (!REG_P (reg))
+ continue;
+
+ add_to_hard_reg_set (&hardregs, GET_MODE (reg),
+ REGNO (reg));
+ }
+ if (hard_reg_set_intersect_p (hardregs, set_up_by_prologue))
+ return true;
+
+ return false;
+}
+
+/* Look for sets of call-saved registers in the first block of the
+ function, and move them down into successor blocks if the register
+ is used only on one path. This exposes more opportunities for
+ shrink-wrapping.
+ These kinds of sets often occur when incoming argument registers are
+ moved to call-saved registers because their values are live across
+ one or more calls during the function. */
+
+static void
+prepare_shrink_wrap (basic_block entry_block)
+{
+ rtx insn, curr;
+ FOR_BB_INSNS_SAFE (entry_block, insn, curr)
+ {
+ basic_block next_bb;
+ edge e, live_edge;
+ edge_iterator ei;
+ rtx set, scan;
+ unsigned destreg, srcreg;
+
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+ set = single_set (insn);
+ if (!set)
+ continue;
+
+ if (!REG_P (SET_SRC (set)) || !REG_P (SET_DEST (set)))
+ continue;
+ srcreg = REGNO (SET_SRC (set));
+ destreg = REGNO (SET_DEST (set));
+ if (hard_regno_nregs[srcreg][GET_MODE (SET_SRC (set))] > 1
+ || hard_regno_nregs[destreg][GET_MODE (SET_DEST (set))] > 1)
+ continue;
+
+ next_bb = entry_block;
+ scan = insn;
+
+ for (;;)
+ {
+ live_edge = NULL;
+ /* Try to find a single edge across which the register is live.
+ If we find one, we'll try to move the set across this edge. */
+ FOR_EACH_EDGE (e, ei, next_bb->succs)
+ {
+ if (REGNO_REG_SET_P (df_get_live_in (e->dest), destreg))
+ {
+ if (live_edge)
+ {
+ live_edge = NULL;
+ break;
+ }
+ live_edge = e;
+ }
+ }
+ if (!live_edge)
+ break;
+ /* We can sometimes encounter dead code. Don't try to move it
+ into the exit block. */
+ if (live_edge->dest == EXIT_BLOCK_PTR)
+ break;
+ if (EDGE_COUNT (live_edge->dest->preds) > 1)
+ break;
+ while (scan != BB_END (next_bb))
+ {
+ scan = NEXT_INSN (scan);
+ if (NONDEBUG_INSN_P (scan))
+ {
+ rtx link;
+ HARD_REG_SET set_regs;
+
+ CLEAR_HARD_REG_SET (set_regs);
+ note_stores (PATTERN (scan), record_hard_reg_sets,
+ &set_regs);
+ if (CALL_P (scan))
+ IOR_HARD_REG_SET (set_regs, call_used_reg_set);
+ for (link = REG_NOTES (scan); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_INC)
+ record_hard_reg_sets (XEXP (link, 0), NULL, &set_regs);
+
+ if (TEST_HARD_REG_BIT (set_regs, srcreg)
+ || reg_referenced_p (SET_DEST (set),
+ PATTERN (scan)))
+ {
+ scan = NULL_RTX;
+ break;
+ }
+ if (CALL_P (scan))
+ {
+ rtx link = CALL_INSN_FUNCTION_USAGE (scan);
+ while (link)
+ {
+ rtx tmp = XEXP (link, 0);
+ if (GET_CODE (tmp) == USE
+ && reg_referenced_p (SET_DEST (set), tmp))
+ break;
+ link = XEXP (link, 1);
+ }
+ if (link)
+ {
+ scan = NULL_RTX;
+ break;
+ }
+ }
+ }
+ }
+ if (!scan)
+ break;
+ next_bb = live_edge->dest;
+ }
+
+ if (next_bb != entry_block)
+ {
+ rtx after = BB_HEAD (next_bb);
+ while (!NOTE_P (after)
+ || NOTE_KIND (after) != NOTE_INSN_BASIC_BLOCK)
+ after = NEXT_INSN (after);
+ emit_insn_after (PATTERN (insn), after);
+ delete_insn (insn);
+ }
+ }
+}
+
+#endif
+
#ifdef HAVE_return
/* Insert use of return register before the end of BB. */
@@ -5299,45 +5498,165 @@ emit_use_return_register_into_block (basic_block bb)
emit_insn_before (seq, BB_END (bb));
}
-/* Insert gen_return at the end of block BB. This also means updating
- block_for_insn appropriately. */
+
+/* Create a return pattern, either simple_return or return, depending on
+ simple_p. */
+
+static rtx
+gen_return_pattern (bool simple_p)
+{
+#ifdef HAVE_simple_return
+ return simple_p ? gen_simple_return () : gen_return ();
+#else
+ gcc_assert (!simple_p);
+ return gen_return ();
+#endif
+}
+
+/* Insert an appropriate return pattern at the end of block BB. This
+ also means updating block_for_insn appropriately. SIMPLE_P is
+ the same as in gen_return_pattern and passed to it. */
static void
-emit_return_into_block (basic_block bb)
+emit_return_into_block (bool simple_p, basic_block bb)
{
- rtx jump = emit_jump_insn_after (gen_return (), BB_END (bb));
- rtx pat = PATTERN (jump);
+ rtx jump, pat;
+ jump = emit_jump_insn_after (gen_return_pattern (simple_p), BB_END (bb));
+ pat = PATTERN (jump);
if (GET_CODE (pat) == PARALLEL)
pat = XVECEXP (pat, 0, 0);
gcc_assert (ANY_RETURN_P (pat));
JUMP_LABEL (jump) = pat;
}
-#endif /* HAVE_return */
+#endif
+
+/* Set JUMP_LABEL for a return insn. */
+
+void
+set_return_jump_label (rtx returnjump)
+{
+ rtx pat = PATTERN (returnjump);
+ if (GET_CODE (pat) == PARALLEL)
+ pat = XVECEXP (pat, 0, 0);
+ if (ANY_RETURN_P (pat))
+ JUMP_LABEL (returnjump) = pat;
+ else
+ JUMP_LABEL (returnjump) = ret_rtx;
+}
+
+/* Return true if BB has any active insns. */
+static bool
+bb_active_p (basic_block bb)
+{
+ rtx label;
+
+ /* Test whether there are active instructions in BB. */
+ label = BB_END (bb);
+ while (label && !LABEL_P (label))
+ {
+ if (active_insn_p (label))
+ break;
+ label = PREV_INSN (label);
+ }
+ return BB_HEAD (bb) != label || !LABEL_P (label);
+}
/* Generate the prologue and epilogue RTL if the machine supports it. Thread
this into place with notes indicating where the prologue ends and where
- the epilogue begins. Update the basic block information when possible. */
+ the epilogue begins. Update the basic block information when possible.
+
+ Notes on epilogue placement:
+ There are several kinds of edges to the exit block:
+ * a single fallthru edge from LAST_BB
+ * possibly, edges from blocks containing sibcalls
+ * possibly, fake edges from infinite loops
+
+ The epilogue is always emitted on the fallthru edge from the last basic
+ block in the function, LAST_BB, into the exit block.
+
+ If LAST_BB is empty except for a label, it is the target of every
+ other basic block in the function that ends in a return. If a
+ target has a return or simple_return pattern (possibly with
+ conditional variants), these basic blocks can be changed so that a
+ return insn is emitted into them, and their target is adjusted to
+ the real exit block.
+
+ Notes on shrink wrapping: We implement a fairly conservative
+ version of shrink-wrapping rather than the textbook one. We only
+ generate a single prologue and a single epilogue. This is
+ sufficient to catch a number of interesting cases involving early
+ exits.
+
+ First, we identify the blocks that require the prologue to occur before
+ them. These are the ones that modify a call-saved register, or reference
+ any of the stack or frame pointer registers. To simplify things, we then
+ mark everything reachable from these blocks as also requiring a prologue.
+ This takes care of loops automatically, and avoids the need to examine
+ whether MEMs reference the frame, since it is sufficient to check for
+ occurrences of the stack or frame pointer.
+
+ We then compute the set of blocks for which the need for a prologue
+ is anticipatable (borrowing terminology from the shrink-wrapping
+ description in Muchnick's book). These are the blocks which either
+ require a prologue themselves, or those that have only successors
+ where the prologue is anticipatable. The prologue needs to be
+ inserted on all edges from BB1->BB2 where BB2 is in ANTIC and BB1
+ is not. For the moment, we ensure that only one such edge exists.
+
+ The epilogue is placed as described above, but we make a
+ distinction between inserting return and simple_return patterns
+ when modifying other blocks that end in a return. Blocks that end
+ in a sibcall omit the sibcall_epilogue if the block is not in
+ ANTIC. */
static void
thread_prologue_and_epilogue_insns (void)
{
bool inserted;
+ basic_block last_bb;
+ bool last_bb_active ATTRIBUTE_UNUSED;
+#ifdef HAVE_simple_return
+ VEC (rtx, heap) *unconverted_simple_returns = NULL;
+ basic_block simple_return_block_hot = NULL;
+ basic_block simple_return_block_cold = NULL;
+ bool nonempty_prologue;
+#endif
+ rtx returnjump ATTRIBUTE_UNUSED;
rtx seq ATTRIBUTE_UNUSED, epilogue_end ATTRIBUTE_UNUSED;
- edge entry_edge, e;
+ rtx prologue_seq ATTRIBUTE_UNUSED, split_prologue_seq ATTRIBUTE_UNUSED;
+ edge e, entry_edge, orig_entry_edge, exit_fallthru_edge;
edge_iterator ei;
+ bitmap_head bb_flags;
+
+ df_analyze ();
rtl_profile_for_bb (ENTRY_BLOCK_PTR);
inserted = false;
seq = NULL_RTX;
epilogue_end = NULL_RTX;
+ returnjump = NULL_RTX;
/* Can't deal with multiple successors of the entry block at the
moment. Function should always have at least one entry
point. */
gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
entry_edge = single_succ_edge (ENTRY_BLOCK_PTR);
+ orig_entry_edge = entry_edge;
+ exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
+ if (exit_fallthru_edge != NULL)
+ {
+ last_bb = exit_fallthru_edge->src;
+ last_bb_active = bb_active_p (last_bb);
+ }
+ else
+ {
+ last_bb = NULL;
+ last_bb_active = false;
+ }
+
+ split_prologue_seq = NULL_RTX;
if (flag_split_stack
&& (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (cfun->decl))
== NULL))
@@ -5349,17 +5668,15 @@ thread_prologue_and_epilogue_insns (void)
start_sequence ();
emit_insn (gen_split_stack_prologue ());
- seq = get_insns ();
+ split_prologue_seq = get_insns ();
end_sequence ();
- record_insns (seq, NULL, &prologue_insn_hash);
- set_insn_locators (seq, prologue_locator);
-
- insert_insn_on_edge (seq, entry_edge);
- inserted = true;
+ record_insns (split_prologue_seq, NULL, &prologue_insn_hash);
+ set_insn_locators (split_prologue_seq, prologue_locator);
#endif
}
+ prologue_seq = NULL_RTX;
#ifdef HAVE_prologue
if (HAVE_prologue)
{
@@ -5382,15 +5699,238 @@ thread_prologue_and_epilogue_insns (void)
if (!targetm.profile_before_prologue () && crtl->profile)
emit_insn (gen_blockage ());
- seq = get_insns ();
+ prologue_seq = get_insns ();
end_sequence ();
- set_insn_locators (seq, prologue_locator);
+ set_insn_locators (prologue_seq, prologue_locator);
+ }
+#endif
- insert_insn_on_edge (seq, entry_edge);
- inserted = true;
+ bitmap_initialize (&bb_flags, &bitmap_default_obstack);
+
+#ifdef HAVE_simple_return
+ /* Try to perform a kind of shrink-wrapping, making sure the
+ prologue/epilogue is emitted only around those parts of the
+ function that require it. */
+
+ nonempty_prologue = false;
+ for (seq = prologue_seq; seq; seq = NEXT_INSN (seq))
+ if (!NOTE_P (seq) || NOTE_KIND (seq) != NOTE_INSN_PROLOGUE_END)
+ {
+ nonempty_prologue = true;
+ break;
+ }
+
+ if (flag_shrink_wrap && HAVE_simple_return
+ && (targetm.profile_before_prologue () || !crtl->profile)
+ && nonempty_prologue && !crtl->calls_eh_return)
+ {
+ HARD_REG_SET prologue_clobbered, prologue_used, live_on_edge;
+ HARD_REG_SET set_up_by_prologue;
+ rtx p_insn;
+
+ VEC(basic_block, heap) *vec;
+ basic_block bb;
+ bitmap_head bb_antic_flags;
+ bitmap_head bb_on_list;
+
+ if (dump_file)
+ fprintf (dump_file, "Attempting shrink-wrapping optimization.\n");
+
+ /* Compute the registers set and used in the prologue. */
+ CLEAR_HARD_REG_SET (prologue_clobbered);
+ CLEAR_HARD_REG_SET (prologue_used);
+ for (p_insn = prologue_seq; p_insn; p_insn = NEXT_INSN (p_insn))
+ {
+ HARD_REG_SET this_used;
+ if (!NONDEBUG_INSN_P (p_insn))
+ continue;
+
+ CLEAR_HARD_REG_SET (this_used);
+ note_uses (&PATTERN (p_insn), record_hard_reg_uses,
+ &this_used);
+ AND_COMPL_HARD_REG_SET (this_used, prologue_clobbered);
+ IOR_HARD_REG_SET (prologue_used, this_used);
+ note_stores (PATTERN (p_insn), record_hard_reg_sets,
+ &prologue_clobbered);
+ }
+
+ prepare_shrink_wrap (entry_edge->dest);
+
+ /* That may have inserted instructions into the last block. */
+ if (last_bb && !last_bb_active)
+ last_bb_active = bb_active_p (last_bb);
+
+ bitmap_initialize (&bb_antic_flags, &bitmap_default_obstack);
+ bitmap_initialize (&bb_on_list, &bitmap_default_obstack);
+
+ /* Find the set of basic blocks that require a stack frame. */
+
+ vec = VEC_alloc (basic_block, heap, n_basic_blocks);
+
+ CLEAR_HARD_REG_SET (set_up_by_prologue);
+ add_to_hard_reg_set (&set_up_by_prologue, Pmode, STACK_POINTER_REGNUM);
+ add_to_hard_reg_set (&set_up_by_prologue, Pmode, ARG_POINTER_REGNUM);
+ if (frame_pointer_needed)
+ add_to_hard_reg_set (&set_up_by_prologue, Pmode,
+ HARD_FRAME_POINTER_REGNUM);
+ if (pic_offset_table_rtx)
+ add_to_hard_reg_set (&set_up_by_prologue, Pmode,
+ PIC_OFFSET_TABLE_REGNUM);
+
+ FOR_EACH_BB (bb)
+ {
+ rtx insn;
+ /* As a special case, check for jumps to the last bb that
+ cannot successfully be converted to simple_returns later
+ on, and mark them as requiring a frame. These are
+ conditional jumps that jump to their fallthru block, so
+ it's not a case that is expected to occur often. */
+ if (JUMP_P (BB_END (bb)) && any_condjump_p (BB_END (bb))
+ && single_succ_p (bb)
+ && !last_bb_active
+ && single_succ (bb) == last_bb)
+ {
+ bitmap_set_bit (&bb_flags, bb->index);
+ VEC_quick_push (basic_block, vec, bb);
+ }
+ else
+ FOR_BB_INSNS (bb, insn)
+ if (requires_stack_frame_p (insn, prologue_used,
+ set_up_by_prologue))
+ {
+ bitmap_set_bit (&bb_flags, bb->index);
+ VEC_quick_push (basic_block, vec, bb);
+ break;
+ }
+ }
+
+ /* For every basic block that needs a prologue, mark all blocks
+ reachable from it, so as to ensure they are also seen as
+ requiring a prologue. */
+ while (!VEC_empty (basic_block, vec))
+ {
+ basic_block tmp_bb = VEC_pop (basic_block, vec);
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
+ if (e->dest != EXIT_BLOCK_PTR
+ && bitmap_set_bit (&bb_flags, e->dest->index))
+ VEC_quick_push (basic_block, vec, e->dest);
+ }
+ /* If the last basic block contains only a label, we'll be able
+ to convert jumps to it to (potentially conditional) return
+ insns later. This means we don't necessarily need a prologue
+ for paths reaching it. */
+ if (last_bb)
+ {
+ if (!last_bb_active)
+ bitmap_clear_bit (&bb_flags, last_bb->index);
+ else if (!bitmap_bit_p (&bb_flags, last_bb->index))
+ goto fail_shrinkwrap;
+ }
+
+ /* Now walk backwards from every block that is marked as needing
+ a prologue to compute the bb_antic_flags bitmap. */
+ bitmap_copy (&bb_antic_flags, &bb_flags);
+ FOR_EACH_BB (bb)
+ {
+ edge e;
+ edge_iterator ei;
+ if (!bitmap_bit_p (&bb_flags, bb->index))
+ continue;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index)
+ && bitmap_set_bit (&bb_on_list, e->src->index))
+ VEC_quick_push (basic_block, vec, e->src);
+ }
+ while (!VEC_empty (basic_block, vec))
+ {
+ basic_block tmp_bb = VEC_pop (basic_block, vec);
+ edge e;
+ edge_iterator ei;
+ bool all_set = true;
+
+ bitmap_clear_bit (&bb_on_list, tmp_bb->index);
+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
+ if (!bitmap_bit_p (&bb_antic_flags, e->dest->index))
+ {
+ all_set = false;
+ break;
+ }
+
+ if (all_set)
+ {
+ bitmap_set_bit (&bb_antic_flags, tmp_bb->index);
+ FOR_EACH_EDGE (e, ei, tmp_bb->preds)
+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index)
+ && bitmap_set_bit (&bb_on_list, e->src->index))
+ VEC_quick_push (basic_block, vec, e->src);
+ }
+ }
+ /* Find exactly one edge that leads to a block in ANTIC from
+ a block that isn't. */
+ if (!bitmap_bit_p (&bb_antic_flags, entry_edge->dest->index))
+ FOR_EACH_BB (bb)
+ {
+ if (!bitmap_bit_p (&bb_antic_flags, bb->index))
+ continue;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
+ {
+ if (entry_edge != orig_entry_edge)
+ {
+ entry_edge = orig_entry_edge;
+ if (dump_file)
+ fprintf (dump_file, "More than one candidate edge.\n");
+ goto fail_shrinkwrap;
+ }
+ if (dump_file)
+ fprintf (dump_file, "Found candidate edge for "
+ "shrink-wrapping, %d->%d.\n", e->src->index,
+ e->dest->index);
+ entry_edge = e;
+ }
+ }
+
+ /* Test whether the prologue is known to clobber any register
+ (other than FP or SP) which are live on the edge. */
+ CLEAR_HARD_REG_BIT (prologue_clobbered, STACK_POINTER_REGNUM);
+ if (frame_pointer_needed)
+ CLEAR_HARD_REG_BIT (prologue_clobbered, HARD_FRAME_POINTER_REGNUM);
+ CLEAR_HARD_REG_SET (live_on_edge);
+ reg_set_to_hard_reg_set (&live_on_edge,
+ df_get_live_in (entry_edge->dest));
+ if (hard_reg_set_intersect_p (live_on_edge, prologue_clobbered))
+ {
+ entry_edge = orig_entry_edge;
+ if (dump_file)
+ fprintf (dump_file, "Shrink-wrapping aborted due to clobber.\n");
+ }
+ else if (entry_edge != orig_entry_edge)
+ {
+ crtl->shrink_wrapped = true;
+ if (dump_file)
+ fprintf (dump_file, "Performing shrink-wrapping.\n");
+ }
+
+ fail_shrinkwrap:
+ bitmap_clear (&bb_antic_flags);
+ bitmap_clear (&bb_on_list);
+ VEC_free (basic_block, heap, vec);
}
#endif
+ if (split_prologue_seq != NULL_RTX)
+ {
+ insert_insn_on_edge (split_prologue_seq, orig_entry_edge);
+ inserted = true;
+ }
+ if (prologue_seq != NULL_RTX)
+ {
+ insert_insn_on_edge (prologue_seq, entry_edge);
+ inserted = true;
+ }
+
/* If the exit block has no non-fake predecessors, we don't need
an epilogue. */
FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
@@ -5400,110 +5940,147 @@ thread_prologue_and_epilogue_insns (void)
goto epilogue_done;
rtl_profile_for_bb (EXIT_BLOCK_PTR);
+
#ifdef HAVE_return
- if (optimize && HAVE_return)
+ /* If we're allowed to generate a simple return instruction, then by
+ definition we don't need a full epilogue. If the last basic
+ block before the exit block does not contain active instructions,
+ examine its predecessors and try to emit (conditional) return
+ instructions. */
+ if (optimize && !last_bb_active
+ && (HAVE_return || entry_edge != orig_entry_edge))
{
- /* If we're allowed to generate a simple return instruction,
- then by definition we don't need a full epilogue. Examine
- the block that falls through to EXIT. If it does not
- contain any code, examine its predecessors and try to
- emit (conditional) return instructions. */
-
- basic_block last;
+ edge_iterator ei2;
+ int i;
+ basic_block bb;
rtx label;
+ VEC(basic_block,heap) *src_bbs;
- e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
- if (e == NULL)
+ if (exit_fallthru_edge == NULL)
goto epilogue_done;
- last = e->src;
+ label = BB_HEAD (last_bb);
- /* Verify that there are no active instructions in the last block. */
- label = BB_END (last);
- while (label && !LABEL_P (label))
- {
- if (active_insn_p (label))
- break;
- label = PREV_INSN (label);
- }
+ src_bbs = VEC_alloc (basic_block, heap, EDGE_COUNT (last_bb->preds));
+ FOR_EACH_EDGE (e, ei2, last_bb->preds)
+ if (e->src != ENTRY_BLOCK_PTR)
+ VEC_quick_push (basic_block, src_bbs, e->src);
- if (BB_HEAD (last) == label && LABEL_P (label))
+ FOR_EACH_VEC_ELT (basic_block, src_bbs, i, bb)
{
- edge_iterator ei2;
-
- for (ei2 = ei_start (last->preds); (e = ei_safe_edge (ei2)); )
- {
- basic_block bb = e->src;
- rtx jump;
-
- if (bb == ENTRY_BLOCK_PTR)
- {
- ei_next (&ei2);
- continue;
- }
+ bool simple_p;
+ rtx jump;
+ e = find_edge (bb, last_bb);
- jump = BB_END (bb);
- if (!JUMP_P (jump) || JUMP_LABEL (jump) != label)
- {
- ei_next (&ei2);
- continue;
- }
+ jump = BB_END (bb);
- /* If we have an unconditional jump, we can replace that
- with a simple return instruction. */
- if (simplejump_p (jump))
- {
- /* The use of the return register might be present in the exit
- fallthru block. Either:
- - removing the use is safe, and we should remove the use in
- the exit fallthru block, or
- - removing the use is not safe, and we should add it here.
- For now, we conservatively choose the latter. Either of the
- 2 helps in crossjumping. */
- emit_use_return_register_into_block (bb);
-
- emit_return_into_block (bb);
- delete_insn (jump);
- }
+#ifdef HAVE_simple_return
+ simple_p = (entry_edge != orig_entry_edge
+ && !bitmap_bit_p (&bb_flags, bb->index));
+#else
+ simple_p = false;
+#endif
- /* If we have a conditional jump, we can try to replace
- that with a conditional return instruction. */
- else if (condjump_p (jump))
- {
- if (! redirect_jump (jump, ret_rtx, 0))
- {
- ei_next (&ei2);
- continue;
- }
+ if (!simple_p
+ && (!HAVE_return || !JUMP_P (jump)
+ || JUMP_LABEL (jump) != label))
+ continue;
- /* See comment in simple_jump_p case above. */
- emit_use_return_register_into_block (bb);
+ /* If we have an unconditional jump, we can replace that
+ with a simple return instruction. */
+ if (!JUMP_P (jump))
+ {
+ emit_barrier_after (BB_END (bb));
+ emit_return_into_block (simple_p, bb);
+ }
+ else if (simplejump_p (jump))
+ {
+ /* The use of the return register might be present in the exit
+ fallthru block. Either:
+ - removing the use is safe, and we should remove the use in
+ the exit fallthru block, or
+ - removing the use is not safe, and we should add it here.
+ For now, we conservatively choose the latter. Either of the
+ 2 helps in crossjumping. */
+ emit_use_return_register_into_block (bb);
+
+ emit_return_into_block (simple_p, bb);
+ delete_insn (jump);
+ }
+ else if (condjump_p (jump) && JUMP_LABEL (jump) != label)
+ {
+ basic_block new_bb;
+ edge new_e;
+
+ gcc_assert (simple_p);
+ new_bb = split_edge (e);
+ emit_barrier_after (BB_END (new_bb));
+ emit_return_into_block (simple_p, new_bb);
+#ifdef HAVE_simple_return
+ if (BB_PARTITION (new_bb) == BB_HOT_PARTITION)
+ simple_return_block_hot = new_bb;
+ else
+ simple_return_block_cold = new_bb;
+#endif
+ new_e = single_succ_edge (new_bb);
+ redirect_edge_succ (new_e, EXIT_BLOCK_PTR);
- /* If this block has only one successor, it both jumps
- and falls through to the fallthru block, so we can't
- delete the edge. */
- if (single_succ_p (bb))
- {
- ei_next (&ei2);
- continue;
- }
- }
+ continue;
+ }
+ /* If we have a conditional jump branching to the last
+ block, we can try to replace that with a conditional
+ return instruction. */
+ else if (condjump_p (jump))
+ {
+ rtx dest;
+ if (simple_p)
+ dest = simple_return_rtx;
else
+ dest = ret_rtx;
+ if (! redirect_jump (jump, dest, 0))
{
- ei_next (&ei2);
+#ifdef HAVE_simple_return
+ if (simple_p)
+ VEC_safe_push (rtx, heap,
+ unconverted_simple_returns, jump);
+#endif
continue;
}
- /* Fix up the CFG for the successful change we just made. */
- redirect_edge_succ (e, EXIT_BLOCK_PTR);
+ /* See comment in simple_jump_p case above. */
+ emit_use_return_register_into_block (bb);
+
+ /* If this block has only one successor, it both jumps
+ and falls through to the fallthru block, so we can't
+ delete the edge. */
+ if (single_succ_p (bb))
+ continue;
+ }
+ else
+ {
+#ifdef HAVE_simple_return
+ if (simple_p)
+ VEC_safe_push (rtx, heap,
+ unconverted_simple_returns, jump);
+#endif
+ continue;
}
+ /* Fix up the CFG for the successful change we just made. */
+ redirect_edge_succ (e, EXIT_BLOCK_PTR);
+ }
+ VEC_free (basic_block, heap, src_bbs);
+
+ if (HAVE_return)
+ {
/* Emit a return insn for the exit fallthru block. Whether
this is still reachable will be determined later. */
- emit_barrier_after (BB_END (last));
- emit_return_into_block (last);
- epilogue_end = BB_END (last);
- single_succ_edge (last)->flags &= ~EDGE_FALLTHRU;
+ emit_barrier_after (BB_END (last_bb));
+ emit_return_into_block (false, last_bb);
+ epilogue_end = BB_END (last_bb);
+ if (JUMP_P (epilogue_end))
+ set_return_jump_label (epilogue_end);
+ single_succ_edge (last_bb)->flags &= ~EDGE_FALLTHRU;
goto epilogue_done;
}
}
@@ -5540,20 +6117,15 @@ thread_prologue_and_epilogue_insns (void)
}
#endif
- /* Find the edge that falls through to EXIT. Other edges may exist
- due to RETURN instructions, but those don't need epilogues.
- There really shouldn't be a mixture -- either all should have
- been converted or none, however... */
+ /* If nothing falls through into the exit block, we don't need an
+ epilogue. */
- e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
- if (e == NULL)
+ if (exit_fallthru_edge == NULL)
goto epilogue_done;
#ifdef HAVE_epilogue
if (HAVE_epilogue)
{
- rtx returnjump;
-
start_sequence ();
epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG);
seq = gen_epilogue ();
@@ -5564,40 +6136,30 @@ thread_prologue_and_epilogue_insns (void)
record_insns (seq, NULL, &epilogue_insn_hash);
set_insn_locators (seq, epilogue_locator);
- returnjump = get_last_insn ();
seq = get_insns ();
+ returnjump = get_last_insn ();
end_sequence ();
- insert_insn_on_edge (seq, e);
+ insert_insn_on_edge (seq, exit_fallthru_edge);
inserted = true;
if (JUMP_P (returnjump))
- {
- rtx pat = PATTERN (returnjump);
- if (GET_CODE (pat) == PARALLEL)
- pat = XVECEXP (pat, 0, 0);
- if (ANY_RETURN_P (pat))
- JUMP_LABEL (returnjump) = pat;
- else
- JUMP_LABEL (returnjump) = ret_rtx;
- }
- else
- returnjump = NULL_RTX;
+ set_return_jump_label (returnjump);
}
else
#endif
{
basic_block cur_bb;
- if (! next_active_insn (BB_END (e->src)))
+ if (! next_active_insn (BB_END (exit_fallthru_edge->src)))
goto epilogue_done;
/* We have a fall-through edge to the exit block, the source is not
at the end of the function, and there will be an assembler epilogue
at the end of the function.
We can't use force_nonfallthru here, because that would try to
- use return. Inserting a jump 'by hand' is extremely messy, so
+ use return. Inserting a jump 'by hand' is extremely messy, so
we take advantage of cfg_layout_finalize using
- fixup_fallthru_exit_predecessor. */
+ fixup_fallthru_exit_predecessor. */
cfg_layout_initialize (0);
FOR_EACH_BB (cur_bb)
if (cur_bb->index >= NUM_FIXED_BLOCKS
@@ -5607,6 +6169,7 @@ thread_prologue_and_epilogue_insns (void)
}
epilogue_done:
+
default_rtl_profile ();
if (inserted)
@@ -5619,6 +6182,7 @@ epilogue_done:
blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
SET_BIT (blocks, entry_edge->dest->index);
+ SET_BIT (blocks, orig_entry_edge->dest->index);
find_many_sub_basic_blocks (blocks);
sbitmap_free (blocks);
@@ -5632,33 +6196,97 @@ epilogue_done:
}
}
+#ifdef HAVE_simple_return
+ /* If there were branches to an empty LAST_BB which we tried to
+ convert to conditional simple_returns, but couldn't for some
+ reason, create a block to hold a simple_return insn and redirect
+ those remaining edges. */
+ if (!VEC_empty (rtx, unconverted_simple_returns))
+ {
+ basic_block exit_pred = EXIT_BLOCK_PTR->prev_bb;
+ rtx jump;
+ int i;
+
+ gcc_assert (entry_edge != orig_entry_edge);
+
+ /* See if we can reuse the last insn that was emitted for the
+ epilogue. */
+ if (returnjump != NULL_RTX
+ && JUMP_LABEL (returnjump) == simple_return_rtx)
+ {
+ edge e = split_block (exit_fallthru_edge->src,
+ PREV_INSN (returnjump));
+ if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
+ simple_return_block_hot = e->dest;
+ else
+ simple_return_block_cold = e->dest;
+ }
+
+ FOR_EACH_VEC_ELT (rtx, unconverted_simple_returns, i, jump)
+ {
+ basic_block src_bb = BLOCK_FOR_INSN (jump);
+ edge e = find_edge (src_bb, last_bb);
+ basic_block *pdest_bb;
+
+ if (BB_PARTITION (src_bb) == BB_HOT_PARTITION)
+ pdest_bb = &simple_return_block_hot;
+ else
+ pdest_bb = &simple_return_block_cold;
+ if (*pdest_bb == NULL)
+ {
+ basic_block bb;
+ rtx start;
+
+ bb = create_basic_block (NULL, NULL, exit_pred);
+ BB_COPY_PARTITION (bb, e->src);
+ start = emit_jump_insn_after (gen_simple_return (),
+ BB_END (bb));
+ JUMP_LABEL (start) = simple_return_rtx;
+ emit_barrier_after (start);
+
+ *pdest_bb = bb;
+ make_edge (bb, EXIT_BLOCK_PTR, 0);
+ }
+ redirect_edge_and_branch_force (e, *pdest_bb);
+ }
+ VEC_free (rtx, heap, unconverted_simple_returns);
+ }
+#endif
+
#ifdef HAVE_sibcall_epilogue
/* Emit sibling epilogues before any sibling call sites. */
for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
{
basic_block bb = e->src;
rtx insn = BB_END (bb);
+ rtx ep_seq;
if (!CALL_P (insn)
- || ! SIBLING_CALL_P (insn))
+ || ! SIBLING_CALL_P (insn)
+ || (entry_edge != orig_entry_edge
+ && !bitmap_bit_p (&bb_flags, bb->index)))
{
ei_next (&ei);
continue;
}
- start_sequence ();
- emit_note (NOTE_INSN_EPILOGUE_BEG);
- emit_insn (gen_sibcall_epilogue ());
- seq = get_insns ();
- end_sequence ();
+ ep_seq = gen_sibcall_epilogue ();
+ if (ep_seq)
+ {
+ start_sequence ();
+ emit_note (NOTE_INSN_EPILOGUE_BEG);
+ emit_insn (ep_seq);
+ seq = get_insns ();
+ end_sequence ();
- /* Retain a map of the epilogue insns. Used in life analysis to
- avoid getting rid of sibcall epilogue insns. Do this before we
- actually emit the sequence. */
- record_insns (seq, NULL, &epilogue_insn_hash);
- set_insn_locators (seq, epilogue_locator);
+ /* Retain a map of the epilogue insns. Used in life analysis to
+ avoid getting rid of sibcall epilogue insns. Do this before we
+ actually emit the sequence. */
+ record_insns (seq, NULL, &epilogue_insn_hash);
+ set_insn_locators (seq, epilogue_locator);
- emit_insn_before (seq, insn);
+ emit_insn_before (seq, insn);
+ }
ei_next (&ei);
}
#endif
@@ -5683,6 +6311,8 @@ epilogue_done:
}
#endif
+ bitmap_clear (&bb_flags);
+
/* Threading the prologue and epilogue changes the artificial refs
in the entry and exit blocks. */
epilogue_completed = 1;
diff --git a/gcc/function.h b/gcc/function.h
index ff193bcf389..42e52acaad5 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -435,6 +435,9 @@ struct GTY(()) rtl_data {
function where currently compiled version of it is nothrow. */
bool nothrow;
+ /* True if we performed shrink-wrapping for the current function. */
+ bool shrink_wrapped;
+
/* Like regs_ever_live, but 1 if a reg is set or clobbered from an
asm. Unlike regs_ever_live, elements of this array corresponding
to eliminable regs (like the frame pointer) are set if an asm
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 0820741a051..6063d81daa5 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1817,6 +1817,11 @@ struct file_rule_st files_rules[] = {
REG_EXTENDED, NULL_REGEX,
"gt-objc-objc-act.h", "objc/objc-act.c", NULL_FRULACT },
+ /* objc/objc-map.h gives gt-objc-objc-map.h for objc/objc-map.c ! */
+ { DIR_PREFIX_REGEX "objc/objc-map\\.h$",
+ REG_EXTENDED, NULL_REGEX,
+ "gt-objc-objc-map.h", "objc/objc-map.c", NULL_FRULACT },
+
/* General cases. For header *.h and source *.c files, we need
* special actions to handle the language. */
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index ec4a4733c1d..4c64842ea27 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -253,6 +253,8 @@ static const char * const optabs[] =
"set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
"set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
"set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
+ "set_direct_optab_handler (vec_perm_optab, $A, CODE_FOR_$(vec_perm$a$))",
+ "set_direct_optab_handler (vec_perm_const_optab, $A, CODE_FOR_$(vec_perm_const$a$))",
"set_convert_optab_handler (vcond_optab, $A, $B, CODE_FOR_$(vcond$a$b$))",
"set_convert_optab_handler (vcondu_optab, $A, $B, CODE_FOR_$(vcondu$a$b$))",
"set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
@@ -269,6 +271,10 @@ static const char * const optabs[] =
"set_optab_handler (vec_widen_umult_lo_optab, $A, CODE_FOR_$(vec_widen_umult_lo_$a$))",
"set_optab_handler (vec_widen_smult_hi_optab, $A, CODE_FOR_$(vec_widen_smult_hi_$a$))",
"set_optab_handler (vec_widen_smult_lo_optab, $A, CODE_FOR_$(vec_widen_smult_lo_$a$))",
+ "set_optab_handler (vec_widen_ushiftl_hi_optab, $A, CODE_FOR_$(vec_widen_ushiftl_hi_$a$))",
+ "set_optab_handler (vec_widen_ushiftl_lo_optab, $A, CODE_FOR_$(vec_widen_ushiftl_lo_$a$))",
+ "set_optab_handler (vec_widen_sshiftl_hi_optab, $A, CODE_FOR_$(vec_widen_sshiftl_hi_$a$))",
+ "set_optab_handler (vec_widen_sshiftl_lo_optab, $A, CODE_FOR_$(vec_widen_sshiftl_lo_$a$))",
"set_optab_handler (vec_unpacks_hi_optab, $A, CODE_FOR_$(vec_unpacks_hi_$a$))",
"set_optab_handler (vec_unpacks_lo_optab, $A, CODE_FOR_$(vec_unpacks_lo_$a$))",
"set_optab_handler (vec_unpacku_hi_optab, $A, CODE_FOR_$(vec_unpacku_hi_$a$))",
diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
index 97d25b9b653..e57d61787df 100644
--- a/gcc/ggc-none.c
+++ b/gcc/ggc-none.c
@@ -39,6 +39,15 @@ ggc_alloc_typed_stat (enum gt_types_enum ARG_UNUSED (gte), size_t size
return xmalloc (size);
}
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ return requested_size;
+}
+
void *
ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
{
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 624f02971e5..617a49348d7 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1,6 +1,6 @@
/* "Bag-of-pages" garbage collector for the GNU compiler.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
+ 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -50,6 +50,11 @@ along with GCC; see the file COPYING3. If not see
#define USING_MALLOC_PAGE_GROUPS
#endif
+#if defined(HAVE_MADVISE) && HAVE_DECL_MADVISE && defined(MADV_DONTNEED) \
+ && defined(USING_MMAP)
+# define USING_MADVISE
+#endif
+
/* Strategy:
This garbage-collecting allocator allocates objects on one of a set
@@ -277,6 +282,9 @@ typedef struct page_entry
/* The lg of size of objects allocated from this page. */
unsigned char order;
+ /* Discarded page? */
+ bool discarded;
+
/* A bit vector indicating whether or not objects are in use. The
Nth bit is one if the Nth object on this page is allocated. This
array is dynamically sized. */
@@ -462,7 +470,7 @@ static struct globals
can override this by defining GGC_QUIRE_SIZE explicitly. */
#ifndef GGC_QUIRE_SIZE
# ifdef USING_MMAP
-# define GGC_QUIRE_SIZE 256
+# define GGC_QUIRE_SIZE 512 /* 2MB for 4K pages */
# else
# define GGC_QUIRE_SIZE 16
# endif
@@ -740,6 +748,10 @@ alloc_page (unsigned order)
if (p != NULL)
{
+ if (p->discarded)
+ G.bytes_mapped += p->bytes;
+ p->discarded = false;
+
/* Recycle the allocated memory from this page ... */
*pp = p->next;
page = p->page;
@@ -956,7 +968,42 @@ free_page (page_entry *entry)
static void
release_pages (void)
{
-#ifdef USING_MMAP
+#ifdef USING_MADVISE
+ page_entry *p, *start_p;
+ char *start;
+ size_t len;
+
+ for (p = G.free_pages; p; )
+ {
+ if (p->discarded)
+ {
+ p = p->next;
+ continue;
+ }
+ start = p->page;
+ len = p->bytes;
+ start_p = p;
+ p = p->next;
+ while (p && p->page == start + len)
+ {
+ len += p->bytes;
+ p = p->next;
+ }
+ /* Give the page back to the kernel, but don't free the mapping.
+ This avoids fragmentation in the virtual memory map of the
+ process. Next time we can reuse it by just touching it. */
+ madvise (start, len, MADV_DONTNEED);
+ /* Don't count those pages as mapped to not touch the garbage collector
+ unnecessarily. */
+ G.bytes_mapped -= len;
+ while (start_p != p)
+ {
+ start_p->discarded = true;
+ start_p = start_p->next;
+ }
+ }
+#endif
+#if defined(USING_MMAP) && !defined(USING_MADVISE)
page_entry *p, *next;
char *start;
size_t len;
@@ -1054,6 +1101,47 @@ static unsigned char size_lookup[NUM_SIZE_LOOKUP] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
};
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated, as well as the size
+ order. */
+
+static void
+ggc_round_alloc_size_1 (size_t requested_size,
+ size_t *size_order,
+ size_t *alloced_size)
+{
+ size_t order, object_size;
+
+ if (requested_size < NUM_SIZE_LOOKUP)
+ {
+ order = size_lookup[requested_size];
+ object_size = OBJECT_SIZE (order);
+ }
+ else
+ {
+ order = 10;
+ while (requested_size > (object_size = OBJECT_SIZE (order)))
+ order++;
+ }
+
+ if (size_order)
+ *size_order = order;
+ if (alloced_size)
+ *alloced_size = object_size;
+}
+
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ size_t size = 0;
+
+ ggc_round_alloc_size_1 (requested_size, NULL, &size);
+ return size;
+}
+
/* Typed allocation function. Does nothing special in this collector. */
void *
@@ -1072,17 +1160,7 @@ ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
struct page_entry *entry;
void *result;
- if (size < NUM_SIZE_LOOKUP)
- {
- order = size_lookup[size];
- object_size = OBJECT_SIZE (order);
- }
- else
- {
- order = 10;
- while (size > (object_size = OBJECT_SIZE (order)))
- order++;
- }
+ ggc_round_alloc_size_1 (size, &order, &object_size);
/* If there are non-full pages for this size allocation, they are at
the head of the list. */
diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c
index d0c1d79f53d..79c8c032966 100644
--- a/gcc/ggc-zone.c
+++ b/gcc/ggc-zone.c
@@ -1073,6 +1073,24 @@ free_chunk (char *ptr, size_t size, struct alloc_zone *zone)
fprintf (G.debug_file, "Deallocating object, chunk=%p\n", (void *)chunk);
}
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ size_t size;
+
+ /* Make sure that zero-sized allocations get a unique and freeable
+ pointer. */
+ if (requested_size == 0)
+ size = MAX_ALIGNMENT;
+ else
+ size = (requested_size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT;
+
+ return size;
+}
+
/* Allocate a chunk of memory of at least ORIG_SIZE bytes, in ZONE. */
void *
@@ -1084,14 +1102,7 @@ ggc_internal_alloc_zone_stat (size_t orig_size, struct alloc_zone *zone
struct small_page_entry *entry;
struct alloc_chunk *chunk, **pp;
void *result;
- size_t size = orig_size;
-
- /* Make sure that zero-sized allocations get a unique and freeable
- pointer. */
- if (size == 0)
- size = MAX_ALIGNMENT;
- else
- size = (size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT;
+ size_t size = ggc_alloced_size_for_request (orig_size);
/* Try to allocate the object from several different sources. Each
of these cases is responsible for setting RESULT and SIZE to
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 30eca66c302..704237cc045 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -145,6 +145,8 @@ extern void gt_pch_save (FILE *f);
/* The internal primitive. */
extern void *ggc_internal_alloc_stat (size_t MEM_STAT_DECL);
+extern size_t ggc_round_alloc_size (size_t requested_size);
+
#define ggc_internal_alloc(s) ggc_internal_alloc_stat (s MEM_STAT_INFO)
/* Allocate an object of the specified type and size. */
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index f8e5035e297..aa67d248c53 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -534,25 +534,22 @@ void
gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
{
tree lhs;
- tree tmp = NULL_TREE; /* Silence warning. */
gimple stmt, new_stmt;
gimple_stmt_iterator i;
gimple_seq stmts = gimple_seq_alloc();
struct gimplify_ctx gctx;
- gimple last = NULL;
- gimple laststore = NULL;
+ gimple last;
+ gimple laststore;
tree reaching_vuse;
stmt = gsi_stmt (*si_p);
gcc_assert (is_gimple_call (stmt));
- lhs = gimple_call_lhs (stmt);
- reaching_vuse = gimple_vuse (stmt);
-
push_gimplify_context (&gctx);
gctx.into_ssa = gimple_in_ssa_p (cfun);
+ lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
{
gimplify_and_add (expr, &stmts);
@@ -571,108 +568,83 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
}
}
else
- tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+ {
+ tree tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+ new_stmt = gimple_build_assign (lhs, tmp);
+ i = gsi_last (stmts);
+ gsi_insert_after_without_update (&i, new_stmt,
+ GSI_CONTINUE_LINKING);
+ }
pop_gimplify_context (NULL);
if (gimple_has_location (stmt))
annotate_all_with_location (stmts, gimple_location (stmt));
- /* The replacement can expose previously unreferenced variables. */
- for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
+ /* First iterate over the replacement statements backward, assigning
+ virtual operands to their defining statements. */
+ laststore = NULL;
+ for (i = gsi_last (stmts); !gsi_end_p (i); gsi_prev (&i))
{
- if (last)
- {
- gsi_insert_before (si_p, last, GSI_NEW_STMT);
- gsi_next (si_p);
- }
new_stmt = gsi_stmt (i);
- if (gimple_in_ssa_p (cfun))
- {
- find_new_referenced_vars (new_stmt);
- mark_symbols_for_renaming (new_stmt);
- }
- /* If the new statement has a VUSE, update it with exact SSA name we
- know will reach this one. */
- if (gimple_vuse (new_stmt))
- {
- /* If we've also seen a previous store create a new VDEF for
- the latter one, and make that the new reaching VUSE. */
- if (laststore)
- {
- reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
- gimple_set_vdef (laststore, reaching_vuse);
- update_stmt (laststore);
- laststore = NULL;
- }
- gimple_set_vuse (new_stmt, reaching_vuse);
- gimple_set_modified (new_stmt, true);
- }
if (gimple_assign_single_p (new_stmt)
&& !is_gimple_reg (gimple_assign_lhs (new_stmt)))
{
+ tree vdef;
+ if (!laststore)
+ vdef = gimple_vdef (stmt);
+ else
+ vdef = make_ssa_name (gimple_vop (cfun), new_stmt);
+ gimple_set_vdef (new_stmt, vdef);
+ if (TREE_CODE (vdef) == SSA_NAME)
+ SSA_NAME_DEF_STMT (vdef) = new_stmt;
laststore = new_stmt;
}
- last = new_stmt;
}
- if (lhs == NULL_TREE)
- {
- /* If we replace a call without LHS that has a VDEF and our new
- sequence ends with a store we must make that store have the same
- vdef in order not to break the sequencing. This can happen
- for instance when folding memcpy calls into assignments. */
- if (gimple_vdef (stmt) && laststore)
- {
- gimple_set_vdef (laststore, gimple_vdef (stmt));
- if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
- update_stmt (laststore);
- }
- else if (gimple_in_ssa_p (cfun))
- {
- unlink_stmt_vdef (stmt);
- release_defs (stmt);
- }
- new_stmt = last;
- }
- else
+ /* Second iterate over the statements forward, assigning virtual
+ operands to their uses. */
+ last = NULL;
+ reaching_vuse = gimple_vuse (stmt);
+ for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
{
+ /* Do not insert the last stmt in this loop but remember it
+ for replacing the original statement. */
if (last)
{
gsi_insert_before (si_p, last, GSI_NEW_STMT);
gsi_next (si_p);
}
- if (laststore && is_gimple_reg (lhs))
- {
- gimple_set_vdef (laststore, gimple_vdef (stmt));
- update_stmt (laststore);
- if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
- laststore = NULL;
- }
- else if (laststore)
- {
- reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
- gimple_set_vdef (laststore, reaching_vuse);
- update_stmt (laststore);
- laststore = NULL;
- }
- new_stmt = gimple_build_assign (lhs, tmp);
- if (!is_gimple_reg (tmp))
+ new_stmt = gsi_stmt (i);
+ /* The replacement can expose previously unreferenced variables. */
+ if (gimple_in_ssa_p (cfun))
+ find_new_referenced_vars (new_stmt);
+ /* If the new statement possibly has a VUSE, update it with exact SSA
+ name we know will reach this one. */
+ if (gimple_has_mem_ops (new_stmt))
gimple_set_vuse (new_stmt, reaching_vuse);
- if (!is_gimple_reg (lhs))
+ gimple_set_modified (new_stmt, true);
+ if (gimple_vdef (new_stmt))
+ reaching_vuse = gimple_vdef (new_stmt);
+ last = new_stmt;
+ }
+
+ /* If the new sequence does not do a store release the virtual
+ definition of the original statement. */
+ if (reaching_vuse
+ && reaching_vuse == gimple_vuse (stmt))
+ {
+ tree vdef = gimple_vdef (stmt);
+ if (vdef
+ && TREE_CODE (vdef) == SSA_NAME)
{
- gimple_set_vdef (new_stmt, gimple_vdef (stmt));
- if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = new_stmt;
+ unlink_stmt_vdef (stmt);
+ release_ssa_name (vdef);
}
- else if (reaching_vuse == gimple_vuse (stmt))
- unlink_stmt_vdef (stmt);
}
- gimple_set_location (new_stmt, gimple_location (stmt));
- gsi_replace (si_p, new_stmt, false);
+ /* Finally replace rhe original statement with the last. */
+ gsi_replace (si_p, last, false);
}
/* Return the string length, maximum string length or maximum value of
@@ -828,6 +800,11 @@ gimple_fold_builtin (gimple stmt)
if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
return NULL_TREE;
+ /* Give up for always_inline inline builtins until they are
+ inlined. */
+ if (avoid_folding_inline_builtin (callee))
+ return NULL_TREE;
+
/* If the builtin could not be folded, and it has no argument list,
we're done. */
nargs = gimple_call_num_args (stmt);
@@ -2569,6 +2546,19 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
tree op1 = (*valueize) (gimple_assign_rhs2 (stmt));
tree op2 = (*valueize) (gimple_assign_rhs3 (stmt));
+ /* Fold embedded expressions in ternary codes. */
+ if ((subcode == COND_EXPR
+ || subcode == VEC_COND_EXPR)
+ && COMPARISON_CLASS_P (op0))
+ {
+ tree op00 = (*valueize) (TREE_OPERAND (op0, 0));
+ tree op01 = (*valueize) (TREE_OPERAND (op0, 1));
+ tree tem = fold_binary_loc (loc, TREE_CODE (op0),
+ TREE_TYPE (op0), op00, op01);
+ if (tem)
+ op0 = tem;
+ }
+
return fold_ternary_loc (loc, subcode,
gimple_expr_type (stmt), op0, op1, op2);
}
@@ -2747,10 +2737,12 @@ fold_array_ctor_reference (tree type, tree ctor,
double_int low_bound, elt_size;
double_int index, max_index;
double_int access_index;
- tree domain_type = TYPE_DOMAIN (TREE_TYPE (ctor));
+ tree domain_type = NULL_TREE;
HOST_WIDE_INT inner_offset;
/* Compute low bound and elt size. */
+ if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE)
+ domain_type = TYPE_DOMAIN (TREE_TYPE (ctor));
if (domain_type && TYPE_MIN_VALUE (domain_type))
{
/* Static constructors for variably sized objects makes no sense. */
@@ -2917,7 +2909,8 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
if (TREE_CODE (ctor) == CONSTRUCTOR)
{
- if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE)
+ if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (ctor)) == VECTOR_TYPE)
return fold_array_ctor_reference (type, ctor, offset, size);
else
return fold_nonarray_ctor_reference (type, ctor, offset, size);
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 5c05f842c4c..fd03ba4702b 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -169,7 +169,7 @@ lower_function_body (void)
and insert. */
disp_var = create_tmp_var (ptr_type_node, "setjmpvar");
arg = build_addr (disp_label, current_function_decl);
- t = implicit_built_in_decls[BUILT_IN_SETJMP_DISPATCHER];
+ t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER);
x = gimple_build_call (t, 1, arg);
gimple_call_set_lhs (x, disp_var);
@@ -861,7 +861,7 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi)
/* Build '__builtin_setjmp_setup (BUF, NEXT_LABEL)' and insert. */
arg = build_addr (next_label, current_function_decl);
- t = implicit_built_in_decls[BUILT_IN_SETJMP_SETUP];
+ t = builtin_decl_implicit (BUILT_IN_SETJMP_SETUP);
g = gimple_build_call (t, 2, gimple_call_arg (stmt, 0), arg);
gimple_set_location (g, loc);
gimple_set_block (g, gimple_block (stmt));
@@ -886,7 +886,7 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi)
/* Build '__builtin_setjmp_receiver (NEXT_LABEL)' and insert. */
arg = build_addr (next_label, current_function_decl);
- t = implicit_built_in_decls[BUILT_IN_SETJMP_RECEIVER];
+ t = builtin_decl_implicit (BUILT_IN_SETJMP_RECEIVER);
g = gimple_build_call (t, 1, arg);
gimple_set_location (g, loc);
gimple_set_block (g, gimple_block (stmt));
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 1f6efc993f2..981d5b094d9 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -343,6 +343,8 @@ dump_binary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
case VEC_EXTRACT_ODD_EXPR:
case VEC_INTERLEAVE_HIGH_EXPR:
case VEC_INTERLEAVE_LOW_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
for (p = tree_code_name [(int) code]; *p; p++)
pp_character (buffer, TOUPPER (*p));
pp_string (buffer, " <");
@@ -417,6 +419,16 @@ dump_ternary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false);
pp_string (buffer, ">");
break;
+
+ case VEC_PERM_EXPR:
+ pp_string (buffer, "VEC_PERM_EXPR <");
+ dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false);
+ pp_string (buffer, ">");
+ break;
case REALIGN_LOAD_EXPR:
pp_string (buffer, "REALIGN_LOAD <");
@@ -600,8 +612,6 @@ pp_points_to_solution (pretty_printer *buffer, struct pt_solution *pt)
pp_character (buffer, '}');
if (pt->vars_contains_global)
pp_string (buffer, " (glob)");
- if (pt->vars_contains_restrict)
- pp_string (buffer, " (restr)");
}
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 9b8e1b1d7be..b2874bb071b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -374,7 +374,8 @@ gimple_build_call_from_tree (tree t)
gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t));
if (fndecl
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA)
+ && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
+ || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN))
gimple_call_set_alloca_for_var (call, CALL_ALLOCA_FOR_VAR_P (t));
else
gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t));
@@ -2638,6 +2639,7 @@ get_gimple_rhs_num_ops (enum tree_code code)
|| (SYM) == DOT_PROD_EXPR \
|| (SYM) == REALIGN_LOAD_EXPR \
|| (SYM) == VEC_COND_EXPR \
+ || (SYM) == VEC_PERM_EXPR \
|| (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS \
: ((SYM) == CONSTRUCTOR \
|| (SYM) == OBJ_TYPE_REF \
@@ -5311,9 +5313,24 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
|| gimple_code (stmt) == GIMPLE_COND))
{
for (i = 0; i < gimple_num_ops (stmt); ++i)
- if (gimple_op (stmt, i)
- && TREE_CODE (gimple_op (stmt, i)) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (gimple_op (stmt, i), 0), data);
+ {
+ tree op = gimple_op (stmt, i);
+ if (op == NULL_TREE)
+ ;
+ else if (TREE_CODE (op) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ /* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
+ tree with two operands. */
+ else if (i == 1 && COMPARISON_CLASS_P (op))
+ {
+ if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0), data);
+ if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
+ 0), data);
+ }
+ }
}
else if (is_gimple_call (stmt))
{
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index d7bc818dfb9..8c2c5ac2c9c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1109,12 +1109,12 @@ build_stack_save_restore (gimple *save, gimple *restore)
{
tree tmp_var;
- *save = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_SAVE], 0);
+ *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
gimple_call_set_lhs (*save, tmp_var);
*restore
- = gimple_build_call (implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
+ = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1, tmp_var);
}
@@ -1329,8 +1329,9 @@ gimplify_vla_decl (tree decl, gimple_seq *seq_p)
SET_DECL_VALUE_EXPR (decl, t);
DECL_HAS_VALUE_EXPR_P (decl) = 1;
- t = built_in_decls[BUILT_IN_ALLOCA];
- t = build_call_expr (t, 1, DECL_SIZE_UNIT (decl));
+ t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+ t = build_call_expr (t, 2, DECL_SIZE_UNIT (decl),
+ size_int (DECL_ALIGN (decl)));
/* The call has been built for a variable-sized object. */
CALL_ALLOCA_FOR_VAR_P (t) = 1;
t = fold_convert (ptr_type, t);
@@ -3210,7 +3211,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
to_ptr = build_fold_addr_expr_loc (loc, to);
gimplify_arg (&to_ptr, seq_p, loc);
- t = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ t = builtin_decl_implicit (BUILT_IN_MEMCPY);
gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
@@ -3257,7 +3258,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
to_ptr = build_fold_addr_expr_loc (loc, to);
gimplify_arg (&to_ptr, seq_p, loc);
- t = implicit_built_in_decls[BUILT_IN_MEMSET];
+ t = builtin_decl_implicit (BUILT_IN_MEMSET);
gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
@@ -4680,7 +4681,7 @@ gimplify_variable_sized_compare (tree *expr_p)
arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
src = build_fold_addr_expr_loc (loc, op1);
dest = build_fold_addr_expr_loc (loc, op0);
- t = implicit_built_in_decls[BUILT_IN_MEMCMP];
+ t = builtin_decl_implicit (BUILT_IN_MEMCMP);
t = build_call_expr_loc (loc, t, 3, dest, src, arg);
expr
@@ -7255,8 +7256,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case TRUTH_XOR_EXPR:
{
tree orig_type = TREE_TYPE (*expr_p);
+ tree new_type, xop0, xop1;
*expr_p = gimple_boolify (*expr_p);
- if (!useless_type_conversion_p (orig_type, TREE_TYPE (*expr_p)))
+ new_type = TREE_TYPE (*expr_p);
+ if (!useless_type_conversion_p (orig_type, new_type))
{
*expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
ret = GS_OK;
@@ -7280,12 +7283,24 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
default:
break;
}
-
+ /* Now make sure that operands have compatible type to
+ expression's new_type. */
+ xop0 = TREE_OPERAND (*expr_p, 0);
+ xop1 = TREE_OPERAND (*expr_p, 1);
+ if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
+ TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
+ new_type,
+ xop0);
+ if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
+ TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
+ new_type,
+ xop1);
/* Continue classified as tcc_binary. */
goto expr_2;
}
case FMA_EXPR:
+ case VEC_PERM_EXPR:
/* Classified as tcc_expression. */
goto expr_3;
@@ -7978,24 +7993,24 @@ gimplify_function_tree (tree fndecl)
tree tmp_var;
gimple call;
- x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+ x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
call = gimple_build_call (x, 1, integer_zero_node);
tmp_var = create_tmp_var (ptr_type_node, "return_addr");
gimple_call_set_lhs (call, tmp_var);
gimplify_seq_add_stmt (&cleanup, call);
- x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
+ x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_EXIT);
call = gimple_build_call (x, 2,
build_fold_addr_expr (current_function_decl),
tmp_var);
gimplify_seq_add_stmt (&cleanup, call);
tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
- x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+ x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
call = gimple_build_call (x, 1, integer_zero_node);
tmp_var = create_tmp_var (ptr_type_node, "return_addr");
gimple_call_set_lhs (call, tmp_var);
gimplify_seq_add_stmt (&body, call);
- x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
+ x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_ENTER);
call = gimple_build_call (x, 2,
build_fold_addr_expr (current_function_decl),
tmp_var);
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index 49a0ba40bbd..349ee255382 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -69,8 +69,7 @@ define_builtin(built_in_function bcode, const char* name, const char* libname,
libname, NULL_TREE);
if (const_p)
TREE_READONLY(decl) = 1;
- built_in_decls[bcode] = decl;
- implicit_built_in_decls[bcode] = decl;
+ set_builtin_decl(bcode, decl, true);
builtin_functions[name] = decl;
if (libname != NULL)
{
@@ -2311,14 +2310,13 @@ Gogo::make_trampoline(tree fnaddr, tree closure, source_location location)
x = save_expr(x);
// Initialize the trampoline.
- tree ini = build_call_expr(implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE],
+ tree ini = build_call_expr(builtin_decl_implicit(BUILT_IN_INIT_TRAMPOLINE),
3, x, fnaddr, closure);
// On some targets the trampoline address needs to be adjusted. For
// example, when compiling in Thumb mode on the ARM, the address
// needs to have the low bit set.
- x = build_call_expr(implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE],
- 1, x);
+ x = build_call_expr(builtin_decl_explicit(BUILT_IN_ADJUST_TRAMPOLINE), 1, x);
x = fold_convert(TREE_TYPE(fnaddr), x);
return build2(COMPOUND_EXPR, TREE_TYPE(x), ini, x);
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 9df9402fcf3..f1f7680d004 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -2063,6 +2063,8 @@ Order_eval::variable(Named_object* no)
return TRAVERSE_SKIP_COMPONENTS;
}
+ Expression* orig_init = init;
+
for (Find_eval_ordering::const_iterator p = find_eval_ordering.begin();
p != find_eval_ordering.end();
++p)
@@ -2087,6 +2089,9 @@ Order_eval::variable(Named_object* no)
var->add_preinit_statement(this->gogo_, s);
}
+ if (init != orig_init)
+ var->set_init(init);
+
return TRAVERSE_SKIP_COMPONENTS;
}
diff --git a/gcc/godump.c b/gcc/godump.c
index 11cd32998ec..f9f767c8113 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -920,9 +920,20 @@ go_output_typedef (struct godump_container *container, tree decl)
if (*slot == NULL)
{
*slot = CONST_CAST (char *, name);
- fprintf (go_dump_file,
- "const _%s = " HOST_WIDE_INT_PRINT_DEC "\n",
- name, tree_low_cst (TREE_VALUE (element), 0));
+ fprintf (go_dump_file, "const _%s = ", name);
+ if (host_integerp (TREE_VALUE (element), 0))
+ fprintf (go_dump_file, HOST_WIDE_INT_PRINT_DEC,
+ tree_low_cst (TREE_VALUE (element), 0));
+ else if (host_integerp (TREE_VALUE (element), 1))
+ fprintf (go_dump_file, HOST_WIDE_INT_PRINT_UNSIGNED,
+ ((unsigned HOST_WIDE_INT)
+ tree_low_cst (TREE_VALUE (element), 1)));
+ else
+ fprintf (go_dump_file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ ((unsigned HOST_WIDE_INT)
+ TREE_INT_CST_HIGH (TREE_VALUE (element))),
+ TREE_INT_CST_LOW (TREE_VALUE (element)));
+ fprintf (go_dump_file, "\n");
}
}
pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 1ba44f9c7bb..ae59c333d61 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -132,6 +132,14 @@ hook_void_FILEptr_constcharptr (FILE *a ATTRIBUTE_UNUSED, const char *b ATTRIBUT
{
}
+/* Generic hook that takes (FILE *, rtx) and returns false. */
+bool
+hook_bool_FILEptr_rtx_false (FILE *a ATTRIBUTE_UNUSED,
+ rtx b ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
/* Used for the TARGET_ASM_CAN_OUTPUT_MI_THUNK hook. */
bool
hook_bool_const_tree_hwi_hwi_const_tree_false (const_tree a ATTRIBUTE_UNUSED,
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 54ace243f76..2e10d1fd682 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -63,6 +63,7 @@ extern void hook_void_void (void);
extern void hook_void_constcharptr (const char *);
extern void hook_void_rtx_int (rtx, int);
extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
+extern bool hook_bool_FILEptr_rtx_false (FILE *, rtx);
extern void hook_void_tree (tree);
extern void hook_void_tree_treeptr (tree, tree *);
extern void hook_void_int_int (int, int);
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 272cbb7175f..784e2e8b106 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -4166,6 +4166,64 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
FOR_BB_INSNS (merge_bb, insn)
if (NONDEBUG_INSN_P (insn))
df_simulate_find_defs (insn, merge_set);
+
+ /* If shrink-wrapping, disable this optimization when test_bb is
+ the first basic block and merge_bb exits. The idea is to not
+ move code setting up a return register as that may clobber a
+ register used to pass function parameters, which then must be
+ saved in caller-saved regs. A caller-saved reg requires the
+ prologue, killing a shrink-wrap opportunity. */
+ if ((flag_shrink_wrap && !epilogue_completed)
+ && ENTRY_BLOCK_PTR->next_bb == test_bb
+ && single_succ_p (new_dest)
+ && single_succ (new_dest) == EXIT_BLOCK_PTR
+ && bitmap_intersect_p (df_get_live_in (new_dest), merge_set))
+ {
+ regset return_regs;
+ unsigned int i;
+
+ return_regs = BITMAP_ALLOC (&reg_obstack);
+
+ /* Start off with the intersection of regs used to pass
+ params and regs used to return values. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (FUNCTION_ARG_REGNO_P (i)
+ && targetm.calls.function_value_regno_p (i))
+ bitmap_set_bit (return_regs, INCOMING_REGNO (i));
+
+ bitmap_and_into (return_regs, df_get_live_out (ENTRY_BLOCK_PTR));
+ bitmap_and_into (return_regs, df_get_live_in (EXIT_BLOCK_PTR));
+ if (!bitmap_empty_p (return_regs))
+ {
+ FOR_BB_INSNS_REVERSE (new_dest, insn)
+ if (NONDEBUG_INSN_P (insn))
+ {
+ df_ref *def_rec;
+ unsigned int uid = INSN_UID (insn);
+
+ /* If this insn sets any reg in return_regs.. */
+ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+ {
+ df_ref def = *def_rec;
+ unsigned r = DF_REF_REGNO (def);
+
+ if (bitmap_bit_p (return_regs, r))
+ break;
+ }
+ /* ..then add all reg uses to the set of regs
+ we're interested in. */
+ if (*def_rec)
+ df_simulate_uses (insn, return_regs);
+ }
+ if (bitmap_intersect_p (merge_set, return_regs))
+ {
+ BITMAP_FREE (return_regs);
+ BITMAP_FREE (merge_set);
+ return FALSE;
+ }
+ }
+ BITMAP_FREE (return_regs);
+ }
}
no_body:
diff --git a/gcc/input.c b/gcc/input.c
index e5e051f9eae..a780f5c7ee7 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -1,5 +1,5 @@
/* Data and functions related to line maps and input files.
- Copyright (C) 2004, 2007, 2008, 2009, 2010
+ Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -42,12 +42,103 @@ expand_location (source_location loc)
xloc.sysp = 0;
}
else
- {
- const struct line_map *map = linemap_lookup (line_table, loc);
- xloc.file = map->to_file;
- xloc.line = SOURCE_LINE (map, loc);
- xloc.column = SOURCE_COLUMN (map, loc);
- xloc.sysp = map->sysp != 0;
- };
+ xloc = linemap_expand_location_full (line_table, loc,
+ LRK_SPELLING_LOCATION);
return xloc;
}
+
+#define ONE_K 1024
+#define ONE_M (ONE_K * ONE_K)
+
+/* Display a number as an integer multiple of either:
+ - 1024, if said integer is >= to 10 K (in base 2)
+ - 1024 * 1024, if said integer is >= 10 M in (base 2)
+ */
+#define SCALE(x) ((unsigned long) ((x) < 10 * ONE_K \
+ ? (x) \
+ : ((x) < 10 * ONE_M \
+ ? (x) / ONE_K \
+ : (x) / ONE_M)))
+
+/* For a given integer, display either:
+ - the character 'k', if the number is higher than 10 K (in base 2)
+ but strictly lower than 10 M (in base 2)
+ - the character 'M' if the number is higher than 10 M (in base2)
+ - the charcter ' ' if the number is strictly lower than 10 K */
+#define STAT_LABEL(x) ((x) < 10 * ONE_K ? ' ' : ((x) < 10 * ONE_M ? 'k' : 'M'))
+
+/* Display an integer amount as multiple of 1K or 1M (in base 2).
+ Display the correct unit (either k, M, or ' ') after the amout, as
+ well. */
+#define FORMAT_AMOUNT(size) SCALE (size), STAT_LABEL (size)
+
+/* Dump statistics to stderr about the memory usage of the line_table
+ set of line maps. This also displays some statistics about macro
+ expansion. */
+
+void
+dump_line_table_statistics (void)
+{
+ struct linemap_stats s;
+ long total_used_map_size,
+ macro_maps_size,
+ total_allocated_map_size;
+
+ memset (&s, 0, sizeof (s));
+
+ linemap_get_statistics (line_table, &s);
+
+ macro_maps_size = s.macro_maps_used_size
+ + s.macro_maps_locations_size;
+
+ total_allocated_map_size = s.ordinary_maps_allocated_size
+ + s.macro_maps_allocated_size
+ + s.macro_maps_locations_size;
+
+ total_used_map_size = s.ordinary_maps_used_size
+ + s.macro_maps_used_size
+ + s.macro_maps_locations_size;
+
+ fprintf (stderr, "Number of expanded macros: %5ld\n",
+ s.num_expanded_macros);
+ if (s.num_expanded_macros != 0)
+ fprintf (stderr, "Average number of tokens per macro expansion: %5ld\n",
+ s.num_macro_tokens / s.num_expanded_macros);
+ fprintf (stderr,
+ "\nLine Table allocations during the "
+ "compilation process\n");
+ fprintf (stderr, "Number of ordinary maps used: %5ld%c\n",
+ SCALE (s.num_ordinary_maps_used),
+ STAT_LABEL (s.num_ordinary_maps_used));
+ fprintf (stderr, "Ordinary map used size: %5ld%c\n",
+ SCALE (s.ordinary_maps_used_size),
+ STAT_LABEL (s.ordinary_maps_used_size));
+ fprintf (stderr, "Number of ordinary maps allocated: %5ld%c\n",
+ SCALE (s.num_ordinary_maps_allocated),
+ STAT_LABEL (s.num_ordinary_maps_allocated));
+ fprintf (stderr, "Ordinary maps allocated size: %5ld%c\n",
+ SCALE (s.ordinary_maps_allocated_size),
+ STAT_LABEL (s.ordinary_maps_allocated_size));
+ fprintf (stderr, "Number of macro maps used: %5ld%c\n",
+ SCALE (s.num_macro_maps_used),
+ STAT_LABEL (s.num_macro_maps_used));
+ fprintf (stderr, "Macro maps used size: %5ld%c\n",
+ SCALE (s.macro_maps_used_size),
+ STAT_LABEL (s.macro_maps_used_size));
+ fprintf (stderr, "Macro maps locations size: %5ld%c\n",
+ SCALE (s.macro_maps_locations_size),
+ STAT_LABEL (s.macro_maps_locations_size));
+ fprintf (stderr, "Macro maps size: %5ld%c\n",
+ SCALE (macro_maps_size),
+ STAT_LABEL (macro_maps_size));
+ fprintf (stderr, "Duplicated maps locations size: %5ld%c\n",
+ SCALE (s.duplicated_macro_maps_locations_size),
+ STAT_LABEL (s.duplicated_macro_maps_locations_size));
+ fprintf (stderr, "Total allocated maps size: %5ld%c\n",
+ SCALE (total_allocated_map_size),
+ STAT_LABEL (total_allocated_map_size));
+ fprintf (stderr, "Total used maps size: %5ld%c\n",
+ SCALE (total_used_map_size),
+ STAT_LABEL (total_used_map_size));
+ fprintf (stderr, "\n");
+}
diff --git a/gcc/input.h b/gcc/input.h
index 59290642090..f2f351311fc 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -37,20 +37,6 @@ extern GTY(()) struct line_maps *line_table;
extern char builtins_location_check[(BUILTINS_LOCATION
< RESERVED_LOCATION_COUNT) ? 1 : -1];
-typedef struct
-{
- /* The name of the source file involved. */
- const char *file;
-
- /* The line-location in the source file. */
- int line;
-
- int column;
-
- /* In a system header?. */
- bool sysp;
-} expanded_location;
-
extern expanded_location expand_location (source_location);
/* Historically GCC used location_t, while cpp used source_location.
@@ -61,10 +47,14 @@ extern location_t input_location;
#define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
#define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
+#define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
#define input_line LOCATION_LINE (input_location)
#define input_filename LOCATION_FILE (input_location)
-#define in_system_header_at(LOC) ((expand_location (LOC)).sysp != 0)
+#define in_system_header_at(LOC) \
+ ((linemap_location_in_system_header_p (line_table, LOC)))
#define in_system_header (in_system_header_at (input_location))
+void dump_line_table_statistics (void);
+
#endif
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 8499cb57f42..1820b0cb323 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -90,8 +90,8 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
/* Estimate runtime of function can easilly run into huge numbers with many
- nested loops. Be sure we can compute time * INLINE_SIZE_SCALE in integer.
- For anything larger we use gcov_type. */
+ nested loops. Be sure we can compute time * INLINE_SIZE_SCALE * 2 in an
+ integer. For anything larger we use gcov_type. */
#define MAX_TIME 500000
/* Number of bits in integer, but we really want to be stable across different
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 36212cda67b..82e24cf5a01 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -437,6 +437,7 @@ special_builtin_state (enum pure_const_state_e *state, bool *looping,
case BUILT_IN_RETURN:
case BUILT_IN_UNREACHABLE:
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
case BUILT_IN_STACK_SAVE:
case BUILT_IN_STACK_RESTORE:
case BUILT_IN_EH_POINTER:
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index b16cfb34a97..7e0769fb592 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -958,7 +958,6 @@ split_function (struct split_point *split_point)
tree retval = NULL, real_retval = NULL;
bool split_part_return_p = false;
gimple last_stmt = NULL;
- bool conv_needed = false;
unsigned int i;
tree arg;
@@ -1000,12 +999,8 @@ split_function (struct split_point *split_point)
else
arg = parm;
- if (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm))
- != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
- {
- conv_needed = true;
- arg = fold_convert (DECL_ARG_TYPE (parm), arg);
- }
+ if (!useless_type_conversion_p (DECL_ARG_TYPE (parm), TREE_TYPE (arg)))
+ arg = fold_convert (DECL_ARG_TYPE (parm), arg);
VEC_safe_push (tree, heap, args_to_pass, arg);
}
@@ -1135,14 +1130,13 @@ split_function (struct split_point *split_point)
/* Produce the call statement. */
gsi = gsi_last_bb (call_bb);
- if (conv_needed)
- FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
- if (!is_gimple_val (arg))
- {
- arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
- false, GSI_NEW_STMT);
- VEC_replace (tree, args_to_pass, i, arg);
- }
+ FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
+ if (!is_gimple_val (arg))
+ {
+ arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
+ false, GSI_CONTINUE_LINKING);
+ VEC_replace (tree, args_to_pass, i, arg);
+ }
call = gimple_build_call_vec (node->decl, args_to_pass);
gimple_set_block (call, DECL_INITIAL (current_function_decl));
@@ -1451,7 +1445,7 @@ struct gimple_opt_pass pass_split_functions =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0 /* todo_flags_finish */
+ TODO_verify_all /* todo_flags_finish */
}
};
@@ -1492,6 +1486,6 @@ struct gimple_opt_pass pass_feedback_split_functions =
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0 /* todo_flags_finish */
+ TODO_verify_all /* todo_flags_finish */
}
};
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 5f14cd8787f..ac83a40c50b 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,24 @@
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * jcf-parse.c (set_source_filename): Adjust to the new map API.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * class.c (build_static_field_ref): Delete old interface with two
+ parallel arrays to hold standard builtin declarations, and replace
+ it with a function based interface that can support creating
+ builtins on the fly in the future. Change all uses, and poison
+ the old names. Make sure 0 is not a legitimate builtin index.
+ * decl.c (java_init_decl_processing): Ditto.
+ * except.c (compareAndSwapLong_builtin): Ditto.
+ (compareAndSwapObject_builtin): Ditto.
+ (putVolatile_builtin): Ditto.
+ (define_builtin): Ditto.
+ (check_for_builtin): Ditto.
+ * expr.c (rewrite_arglist_getcaller): Ditto.
+ (expand_java_field_op): Ditto.
+
2011-08-24 Joseph Myers <joseph@codesourcery.com>
* Make-lang.in (CFLAGS-java/jcf-io.o, CFLAGS-java/jcf-path.o):
diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c
index 1e94bcab4d2..5ab345dc472 100644
--- a/gcc/java/builtins.c
+++ b/gcc/java/builtins.c
@@ -324,13 +324,13 @@ compareAndSwapInt_builtin (tree method_return_type ATTRIBUTE_UNUSED,
|| flag_use_atomic_builtins)
{
tree addr, stmt;
+ enum built_in_function fncode = BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4;
UNMARSHAL5 (orig_call);
(void) value_type; /* Avoid set but not used warning. */
addr = build_addr_sum (int_type_node, obj_arg, offset_arg);
- stmt = build_call_expr
- (built_in_decls[BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4],
- 3, addr, expected_arg, value_arg);
+ stmt = build_call_expr (builtin_decl_explicit (fncode),
+ 3, addr, expected_arg, value_arg);
return build_check_this (stmt, this_arg);
}
@@ -351,13 +351,13 @@ compareAndSwapLong_builtin (tree method_return_type ATTRIBUTE_UNUSED,
but not the multi-word versions. */
{
tree addr, stmt;
+ enum built_in_function fncode = BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8;
UNMARSHAL5 (orig_call);
(void) value_type; /* Avoid set but not used warning. */
addr = build_addr_sum (long_type_node, obj_arg, offset_arg);
- stmt = build_call_expr
- (built_in_decls[BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8],
- 3, addr, expected_arg, value_arg);
+ stmt = build_call_expr (builtin_decl_explicit (fncode),
+ 3, addr, expected_arg, value_arg);
return build_check_this (stmt, this_arg);
}
@@ -373,7 +373,7 @@ compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED,
|| flag_use_atomic_builtins)
{
tree addr, stmt;
- int builtin;
+ enum built_in_function builtin;
UNMARSHAL5 (orig_call);
builtin = (POINTER_SIZE == 32
@@ -381,7 +381,7 @@ compareAndSwapObject_builtin (tree method_return_type ATTRIBUTE_UNUSED,
: BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8);
addr = build_addr_sum (value_type, obj_arg, offset_arg);
- stmt = build_call_expr (built_in_decls[builtin],
+ stmt = build_call_expr (builtin_decl_explicit (builtin),
3, addr, expected_arg, value_arg);
return build_check_this (stmt, this_arg);
@@ -401,7 +401,7 @@ putVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED,
= fold_convert (build_pointer_type (build_type_variant (value_type, 0, 1)),
addr);
- stmt = build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0);
+ stmt = build_call_expr (builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE), 0);
modify_stmt = fold_build2 (MODIFY_EXPR, value_type,
build_java_indirect_ref (value_type, addr,
flag_check_references),
@@ -425,8 +425,7 @@ getVolatile_builtin (tree method_return_type ATTRIBUTE_UNUSED,
= fold_convert (build_pointer_type (build_type_variant
(method_return_type, 0, 1)), addr);
- stmt = build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0);
-
+ stmt = build_call_expr (builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE), 0);
tmp = build_decl (BUILTINS_LOCATION, VAR_DECL, NULL, method_return_type);
DECL_IGNORED_P (tmp) = 1;
DECL_ARTIFICIAL (tmp) = 1;
@@ -483,8 +482,7 @@ define_builtin (enum built_in_function val,
if (flags & BUILTIN_CONST)
TREE_READONLY (decl) = 1;
- implicit_built_in_decls[val] = decl;
- built_in_decls[val] = decl;
+ set_builtin_decl (val, decl, true);
}
@@ -627,7 +625,7 @@ check_for_builtin (tree method, tree call)
with the BC-ABI. */
if (flag_indirect_dispatch)
return call;
- fn = built_in_decls[java_builtins[i].builtin_code];
+ fn = builtin_decl_explicit (java_builtins[i].builtin_code);
if (fn == NULL_TREE)
return call;
return java_build_function_call_expr (fn, call);
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 3bb5ff44f6e..ac69319349a 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -1266,7 +1266,7 @@ build_static_field_ref (tree fdecl)
int cpool_index = alloc_constant_fieldref (output_class, fdecl);
tree cache_entry = build_fieldref_cache_entry (cpool_index, fdecl);
tree test
- = build_call_expr (built_in_decls[BUILT_IN_EXPECT], 2,
+ = build_call_expr (builtin_decl_implicit (BUILT_IN_EXPECT), 2,
build2 (EQ_EXPR, boolean_type_node,
cache_entry, null_pointer_node),
boolean_false_node);
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 179a2c3e9aa..1e1db76dc3b 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -1135,7 +1135,7 @@ java_init_decl_processing (void)
initialize_builtins ();
- soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
+ soft_fmod_node = builtin_decl_explicit (BUILT_IN_FMOD);
parse_version ();
}
diff --git a/gcc/java/except.c b/gcc/java/except.c
index f5e5bb9e664..ff9a1063e37 100644
--- a/gcc/java/except.c
+++ b/gcc/java/except.c
@@ -520,8 +520,8 @@ expand_end_java_handler (struct eh_range *range)
type = throwable_type_node;
eh_type = prepare_eh_table_type (type);
- x = build_call_expr (built_in_decls[BUILT_IN_EH_POINTER],
- 1, integer_zero_node);
+ x = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER),
+ 1, integer_zero_node);
x = build2 (MODIFY_EXPR, void_type_node, exc_obj, x);
tsi_link_after (&stmts_i, x, TSI_CONTINUE_LINKING);
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index ec2d9b65d0a..d38311726d3 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -2073,7 +2073,7 @@ static void
rewrite_arglist_getcaller (VEC(tree,gc) **arglist)
{
tree retaddr
- = build_call_expr (built_in_decls[BUILT_IN_RETURN_ADDRESS],
+ = build_call_expr (builtin_decl_explicit (BUILT_IN_RETURN_ADDRESS),
1, integer_zero_node);
DECL_UNINLINABLE (current_function_decl) = 1;
@@ -2933,8 +2933,10 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
field_ref, new_value);
if (TREE_THIS_VOLATILE (field_decl))
- java_add_stmt
- (build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0));
+ {
+ tree sync = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
+ java_add_stmt (build_call_expr (sync, 0));
+ }
java_add_stmt (modify_expr);
}
@@ -2952,8 +2954,10 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
java_add_stmt (modify_expr);
if (TREE_THIS_VOLATILE (field_decl))
- java_add_stmt
- (build_call_expr (built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE], 0));
+ {
+ tree sync = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
+ java_add_stmt (build_call_expr (sync, 0));
+ }
push_value (temp);
}
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 37cea2870a8..04c04f575cf 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -355,7 +355,7 @@ set_source_filename (JCF *jcf, int index)
}
sfname = find_sourcefile (sfname);
- line_table->maps[line_table->used-1].to_file = sfname;
+ ORDINARY_MAP_FILE_NAME (LINEMAPS_LAST_ORDINARY_MAP (line_table)) = sfname;
if (current_class == main_class) main_input_filename = sfname;
}
diff --git a/gcc/jump.c b/gcc/jump.c
index 0273adf4af6..f852f827729 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1086,6 +1086,7 @@ mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
return;
case RETURN:
+ case SIMPLE_RETURN:
if (is_target)
{
gcc_assert (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == x);
@@ -1408,7 +1409,7 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
int i;
const char *fmt;
- if ((code == LABEL_REF && XEXP (x, 0) == olabel)
+ if ((code == LABEL_REF && XEXP (x, 0) == olabel)
|| x == olabel)
{
x = redirect_target (nlabel);
diff --git a/gcc/longlong.h b/gcc/longlong.h
index 82ced170887..30cc2e337f3 100644
--- a/gcc/longlong.h
+++ b/gcc/longlong.h
@@ -365,23 +365,24 @@ UDItype __umulsidi3 (USItype, USItype);
#else
#define smul_ppmm(xh, xl, m0, m1) \
do { \
- register SItype r0 __asm__ ("0"); \
- register SItype r1 __asm__ ("1") = m0; \
+ register SItype __r0 __asm__ ("0"); \
+ register SItype __r1 __asm__ ("1") = (m0); \
\
__asm__ ("mr\t%%r0,%3" \
- : "=r" (r0), "=r" (r1) \
- : "r" (r1), "r" (m1)); \
- (xh) = r0; (xl) = r1; \
+ : "=r" (__r0), "=r" (__r1) \
+ : "r" (__r1), "r" (m1)); \
+ (xh) = __r0; (xl) = __r1; \
} while (0)
+
#define sdiv_qrnnd(q, r, n1, n0, d) \
- do { \
- register SItype r0 __asm__ ("0") = n0; \
- register SItype r1 __asm__ ("1") = n1; \
+ do { \
+ register SItype __r0 __asm__ ("0") = (n1); \
+ register SItype __r1 __asm__ ("1") = (n0); \
\
- __asm__ ("dr\t%%r0,%3" \
- : "=r" (r0), "=r" (r1) \
- : "r" (r0), "r" (r1), "r" (d)); \
- (q) = r0; (r) = r1; \
+ __asm__ ("dr\t%%r0,%4" \
+ : "=r" (__r0), "=r" (__r1) \
+ : "r" (__r0), "r" (__r1), "r" (d)); \
+ (q) = __r1; (r) = __r0; \
} while (0)
#endif /* __zarch__ */
#endif
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 9254b8f9014..833bf84743b 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -54,6 +54,9 @@ static void input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes);
/* Number of LDPR values known to GCC. */
#define LDPR_NUM_KNOWN (LDPR_PREVAILING_DEF_IRONLY_EXP + 1)
+/* All node orders are ofsetted by ORDER_BASE. */
+static int order_base;
+
/* Cgraph streaming is organized as set of record whose type
is indicated by a tag. */
enum LTO_cgraph_tags
@@ -425,6 +428,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_enum (ob->main_stream, LTO_cgraph_tags, LTO_cgraph_last_tag,
tag);
+ streamer_write_hwi_stream (ob->main_stream, node->order);
/* In WPA mode, we only output part of the call-graph. Also, we
fake cgraph node attributes. There are two cases that we care.
@@ -548,6 +552,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
struct bitpack_d bp;
int ref;
+ streamer_write_hwi_stream (ob->main_stream, node->order);
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, node->externally_visible, 1);
@@ -960,7 +965,9 @@ input_node (struct lto_file_decl_data *file_data,
unsigned decl_index;
int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
int clone_ref;
+ int order;
+ order = streamer_read_hwi (ib) + order_base;
clone_ref = streamer_read_hwi (ib);
decl_index = streamer_read_uhwi (ib);
@@ -974,6 +981,10 @@ input_node (struct lto_file_decl_data *file_data,
else
node = cgraph_get_create_node (fn_decl);
+ node->order = order;
+ if (order >= cgraph_order)
+ cgraph_order = order + 1;
+
node->count = streamer_read_hwi (ib);
node->count_materialization_scale = streamer_read_hwi (ib);
@@ -1035,10 +1046,15 @@ input_varpool_node (struct lto_file_decl_data *file_data,
struct bitpack_d bp;
int ref = LCC_NOT_FOUND;
bool non_null_aliasof;
+ int order;
+ order = streamer_read_hwi (ib) + order_base;
decl_index = streamer_read_uhwi (ib);
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
node = varpool_node (var_decl);
+ node->order = order;
+ if (order >= cgraph_order)
+ cgraph_order = order + 1;
node->lto_file_data = file_data;
bp = streamer_read_bitpack (ib);
@@ -1178,6 +1194,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
unsigned i;
tag = streamer_read_enum (ib, LTO_cgraph_tags, LTO_cgraph_last_tag);
+ order_base = cgraph_order;
while (tag)
{
if (tag == LTO_cgraph_edge)
@@ -1196,7 +1213,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
tag = streamer_read_enum (ib, LTO_cgraph_tags, LTO_cgraph_last_tag);
}
- lto_input_toplevel_asms (file_data);
+ lto_input_toplevel_asms (file_data, order_base);
/* AUX pointers should be all non-zero for nodes read from the stream. */
#ifdef ENABLE_CHECKING
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index ef972cab1d0..1847738fbc3 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto-streamer.h"
#include "tree-streamer.h"
#include "tree-pass.h"
+#include "streamer-hooks.h"
/* The table to hold the file names. */
static htab_t file_name_hash_table;
@@ -180,15 +181,23 @@ lto_input_location_bitpack (struct data_in *data_in, struct bitpack_d *bp)
}
-/* Read a location from input block IB. */
+/* Read a location from input block IB.
+ If the input_location streamer hook exists, call it.
+ Otherwise, proceed with reading the location from the
+ expanded location bitpack. */
location_t
lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
{
- struct bitpack_d bp;
+ if (streamer_hooks.input_location)
+ return streamer_hooks.input_location (ib, data_in);
+ else
+ {
+ struct bitpack_d bp;
- bp = streamer_read_bitpack (ib);
- return lto_input_location_bitpack (data_in, &bp);
+ bp = streamer_read_bitpack (ib);
+ return lto_input_location_bitpack (data_in, &bp);
+ }
}
@@ -755,27 +764,40 @@ fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts)
}
}
-/* Read the body of function FN_DECL from DATA_IN using input block IB. */
+
+/* Input the base body of struct function FN from DATA_IN
+ using input block IB. */
static void
-input_function (tree fn_decl, struct data_in *data_in,
- struct lto_input_block *ib)
+input_struct_function_base (struct function *fn, struct data_in *data_in,
+ struct lto_input_block *ib)
{
- struct function *fn;
- enum LTO_tags tag;
- gimple *stmts;
- basic_block bb;
struct bitpack_d bp;
- struct cgraph_node *node;
- tree args, narg, oarg;
int len;
- fn = DECL_STRUCT_FUNCTION (fn_decl);
- tag = streamer_read_record_start (ib);
- clear_line_info (data_in);
+ /* Read the static chain and non-local goto save area. */
+ fn->static_chain_decl = stream_read_tree (ib, data_in);
+ fn->nonlocal_goto_save_area = stream_read_tree (ib, data_in);
- gimple_register_cfg_hooks ();
- lto_tag_check (tag, LTO_function);
+ /* Read all the local symbols. */
+ len = streamer_read_hwi (ib);
+ if (len > 0)
+ {
+ int i;
+ VEC_safe_grow (tree, gc, fn->local_decls, len);
+ for (i = 0; i < len; i++)
+ {
+ tree t = stream_read_tree (ib, data_in);
+ VEC_replace (tree, fn->local_decls, i, t);
+ }
+ }
+
+ /* Input the function start and end loci. */
+ fn->function_start_locus = lto_input_location (ib, data_in);
+ fn->function_end_locus = lto_input_location (ib, data_in);
+
+ /* Input the current IL state of the function. */
+ fn->curr_properties = streamer_read_uhwi (ib);
/* Read all the attributes for FN. */
bp = streamer_read_bitpack (ib);
@@ -793,30 +815,30 @@ input_function (tree fn_decl, struct data_in *data_in,
fn->calls_setjmp = bp_unpack_value (&bp, 1);
fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
fn->va_list_gpr_size = bp_unpack_value (&bp, 8);
+}
- /* Input the function start and end loci. */
- fn->function_start_locus = lto_input_location (ib, data_in);
- fn->function_end_locus = lto_input_location (ib, data_in);
- /* Input the current IL state of the function. */
- fn->curr_properties = streamer_read_uhwi (ib);
+/* Read the body of function FN_DECL from DATA_IN using input block IB. */
- /* Read the static chain and non-local goto save area. */
- fn->static_chain_decl = stream_read_tree (ib, data_in);
- fn->nonlocal_goto_save_area = stream_read_tree (ib, data_in);
+static void
+input_function (tree fn_decl, struct data_in *data_in,
+ struct lto_input_block *ib)
+{
+ struct function *fn;
+ enum LTO_tags tag;
+ gimple *stmts;
+ basic_block bb;
+ struct cgraph_node *node;
+ tree args, narg, oarg;
- /* Read all the local symbols. */
- len = streamer_read_hwi (ib);
- if (len > 0)
- {
- int i;
- VEC_safe_grow (tree, gc, fn->local_decls, len);
- for (i = 0; i < len; i++)
- {
- tree t = stream_read_tree (ib, data_in);
- VEC_replace (tree, fn->local_decls, i, t);
- }
- }
+ fn = DECL_STRUCT_FUNCTION (fn_decl);
+ tag = streamer_read_record_start (ib);
+ clear_line_info (data_in);
+
+ gimple_register_cfg_hooks ();
+ lto_tag_check (tag, LTO_function);
+
+ input_struct_function_base (fn, data_in, ib);
/* Read all function arguments. We need to re-map them here to the
arguments of the merged function declaration. */
@@ -1144,7 +1166,7 @@ lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
/* Input toplevel asms. */
void
-lto_input_toplevel_asms (struct lto_file_decl_data *file_data)
+lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base)
{
size_t len;
const char *data = lto_get_section_data (file_data, LTO_section_asm,
@@ -1173,7 +1195,12 @@ lto_input_toplevel_asms (struct lto_file_decl_data *file_data)
header->lto_header.minor_version);
while ((str = streamer_read_string_cst (data_in, &ib)))
- cgraph_add_asm_node (str);
+ {
+ struct cgraph_asm_node *node = cgraph_add_asm_node (str);
+ node->order = streamer_read_hwi (&ib) + order_base;
+ if (node->order >= cgraph_order)
+ cgraph_order = node->order + 1;
+ }
clear_line_info (data_in);
lto_data_in_delete (data_in);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index d107b916e56..62cf9a1832f 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -172,15 +172,21 @@ lto_output_location_bitpack (struct bitpack_d *bp,
/* Emit location LOC to output block OB.
- When bitpack is handy, it is more space effecient to call
+ If the output_location streamer hook exists, call it.
+ Otherwise, when bitpack is handy, it is more space efficient to call
lto_output_location_bitpack with existing bitpack. */
void
lto_output_location (struct output_block *ob, location_t loc)
{
- struct bitpack_d bp = bitpack_create (ob->main_stream);
- lto_output_location_bitpack (&bp, ob, loc);
- streamer_write_bitpack (&bp);
+ if (streamer_hooks.output_location)
+ streamer_hooks.output_location (ob, loc);
+ else
+ {
+ struct bitpack_d bp = bitpack_create (ob->main_stream);
+ lto_output_location_bitpack (&bp, ob, loc);
+ streamer_write_bitpack (&bp);
+ }
}
@@ -713,36 +719,30 @@ produce_asm (struct output_block *ob, tree fn)
}
-/* Output the body of function NODE->DECL. */
+/* Output the base body of struct function FN using output block OB. */
static void
-output_function (struct cgraph_node *node)
+output_struct_function_base (struct output_block *ob, struct function *fn)
{
struct bitpack_d bp;
- tree function;
- struct function *fn;
- basic_block bb;
- struct output_block *ob;
unsigned i;
tree t;
- function = node->decl;
- fn = DECL_STRUCT_FUNCTION (function);
- ob = create_output_block (LTO_section_function_body);
-
- clear_line_info (ob);
- ob->cgraph_node = node;
-
- gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+ /* Output the static chain and non-local goto save area. */
+ stream_write_tree (ob, fn->static_chain_decl, true);
+ stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
- /* Set current_function_decl and cfun. */
- current_function_decl = function;
- push_cfun (fn);
+ /* Output all the local variables in the function. */
+ streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
+ FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
+ stream_write_tree (ob, t, true);
- /* Make string 0 be a NULL string. */
- streamer_write_char_stream (ob->string_stream, 0);
+ /* Output the function start and end loci. */
+ lto_output_location (ob, fn->function_start_locus);
+ lto_output_location (ob, fn->function_end_locus);
- streamer_write_record_start (ob, LTO_function);
+ /* Output current IL state of the function. */
+ streamer_write_uhwi (ob, fn->curr_properties);
/* Write all the attributes for FN. */
bp = bitpack_create (ob->main_stream);
@@ -761,22 +761,38 @@ output_function (struct cgraph_node *node)
bp_pack_value (&bp, fn->va_list_fpr_size, 8);
bp_pack_value (&bp, fn->va_list_gpr_size, 8);
streamer_write_bitpack (&bp);
+}
- /* Output the function start and end loci. */
- lto_output_location (ob, fn->function_start_locus);
- lto_output_location (ob, fn->function_end_locus);
- /* Output current IL state of the function. */
- streamer_write_uhwi (ob, fn->curr_properties);
+/* Output the body of function NODE->DECL. */
- /* Output the static chain and non-local goto save area. */
- stream_write_tree (ob, fn->static_chain_decl, true);
- stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
+static void
+output_function (struct cgraph_node *node)
+{
+ tree function;
+ struct function *fn;
+ basic_block bb;
+ struct output_block *ob;
- /* Output all the local variables in the function. */
- streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
- FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
- stream_write_tree (ob, t, true);
+ function = node->decl;
+ fn = DECL_STRUCT_FUNCTION (function);
+ ob = create_output_block (LTO_section_function_body);
+
+ clear_line_info (ob);
+ ob->cgraph_node = node;
+
+ gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+ /* Set current_function_decl and cfun. */
+ current_function_decl = function;
+ push_cfun (fn);
+
+ /* Make string 0 be a NULL string. */
+ streamer_write_char_stream (ob->string_stream, 0);
+
+ streamer_write_record_start (ob, LTO_function);
+
+ output_struct_function_base (ob, fn);
/* Output the head of the arguments list. */
stream_write_tree (ob, DECL_ARGUMENTS (function), true);
@@ -954,7 +970,10 @@ lto_output_toplevel_asms (void)
streamer_write_char_stream (ob->string_stream, 0);
for (can = cgraph_asm_nodes; can; can = can->next)
- streamer_write_string_cst (ob, ob->main_stream, can->asm_str);
+ {
+ streamer_write_string_cst (ob, ob->main_stream, can->asm_str);
+ streamer_write_hwi (ob, can->order);
+ }
streamer_write_string_cst (ob, ob->main_stream, NULL_TREE);
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index ee818429328..f3c93682633 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -807,7 +807,7 @@ extern void lto_input_function_body (struct lto_file_decl_data *, tree,
const char *);
extern void lto_input_constructors_and_inits (struct lto_file_decl_data *,
const char *);
-extern void lto_input_toplevel_asms (struct lto_file_decl_data *);
+extern void lto_input_toplevel_asms (struct lto_file_decl_data *, int);
extern struct data_in *lto_data_in_create (struct lto_file_decl_data *,
const char *, unsigned,
VEC(ld_plugin_symbol_resolution_t,heap) *);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index d3d7ffd484e..12f75ada5b7 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,32 @@
+2011-10-09 Andi Kleen <ak@linux.intel.com>
+
+ * lto.c (lto_section_read): Call fatal_error on IO or mmap errors.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * lto-lang.c (def_builtin_1): Delete old interface with two
+ parallel arrays to hold standard builtin declarations, and replace
+ it with a function based interface that can support creating
+ builtins on the fly in the future. Change all uses, and poison
+ the old names. Make sure 0 is not a legitimate builtin index.
+
+2011-10-02 Andi Kleen <ak@linux.intel.com>
+
+ * lto-object.c (lto_obj_add_section_data): Add list.
+ (lto_obj_add_section): Fill in list.
+ (ltoobj_build_section_table): Pass through list.
+ * lto.c (file_data_list): Declare.
+ (create_subid_section_table): Pass arguments directly.
+ Fill in list of file_datas.
+ (lwstate): Delete.
+ (lto_create_files_from_ids): Pass in direct arguments.
+ Don't maintain list.
+ (lto_file_read): Use explicit section and file data lists.
+ (lto_read_all_file_options): Pass in section_list.
+ * lto.h (lto_obj_build_section_table): Add list.
+ (lto_section_slot): Add next.
+ (lto_section_list): Declare.
+
2011-10-02 Jan Hubicka <jh@suse.cz>
PR lto/47247
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index d469fb93b6a..4a5f6fe8ab5 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -499,9 +499,7 @@ def_builtin_1 (enum built_in_function fncode, const char *name,
add_builtin_function (libname, libtype, fncode, fnclass,
NULL, fnattrs);
- built_in_decls[(int) fncode] = decl;
- if (implicit_p)
- implicit_built_in_decls[(int) fncode] = decl;
+ set_builtin_decl (fncode, decl, implicit_p);
}
diff --git a/gcc/lto/lto-object.c b/gcc/lto/lto-object.c
index 3be58dec380..daf3bd002a3 100644
--- a/gcc/lto/lto-object.c
+++ b/gcc/lto/lto-object.c
@@ -204,6 +204,8 @@ struct lto_obj_add_section_data
htab_t section_hash_table;
/* The offset of this file. */
off_t base_offset;
+ /* List in linker order */
+ struct lto_section_list *list;
};
/* This is called for each section in the file. */
@@ -218,6 +220,7 @@ lto_obj_add_section (void *data, const char *name, off_t offset,
char *new_name;
struct lto_section_slot s_slot;
void **slot;
+ struct lto_section_list *list = loasd->list;
if (strncmp (name, LTO_SECTION_NAME_PREFIX,
strlen (LTO_SECTION_NAME_PREFIX)) != 0)
@@ -228,12 +231,21 @@ lto_obj_add_section (void *data, const char *name, off_t offset,
slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
if (*slot == NULL)
{
- struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
+ struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot);
new_slot->name = new_name;
new_slot->start = loasd->base_offset + offset;
new_slot->len = length;
*slot = new_slot;
+
+ if (list != NULL)
+ {
+ if (!list->first)
+ list->first = new_slot;
+ if (list->last)
+ list->last->next = new_slot;
+ list->last = new_slot;
+ }
}
else
{
@@ -248,7 +260,7 @@ lto_obj_add_section (void *data, const char *name, off_t offset,
the start and size of each section in the .o file. */
htab_t
-lto_obj_build_section_table (lto_file *lto_file)
+lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list)
{
struct lto_simple_object *lo = (struct lto_simple_object *) lto_file;
htab_t section_hash_table;
@@ -261,6 +273,7 @@ lto_obj_build_section_table (lto_file *lto_file)
gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL);
loasd.section_hash_table = section_hash_table;
loasd.base_offset = lo->base.offset;
+ loasd.list = list;
errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section,
&loasd, &err);
if (errmsg != NULL)
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 778e33eee01..63af047640d 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1052,6 +1052,12 @@ lto_resolution_read (splay_tree file_ids, FILE *resolution, lto_file *file)
}
}
+/* List of file_decl_datas */
+struct file_data_list
+ {
+ struct lto_file_decl_data *first, *last;
+ };
+
/* Is the name for a id'ed LTO section? */
static int
@@ -1068,11 +1074,10 @@ lto_section_with_id (const char *name, unsigned HOST_WIDE_INT *id)
/* Create file_data of each sub file id */
static int
-create_subid_section_table (void **slot, void *data)
+create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
+ struct file_data_list *list)
{
struct lto_section_slot s_slot, *new_slot;
- struct lto_section_slot *ls = *(struct lto_section_slot **)slot;
- splay_tree file_ids = (splay_tree)data;
unsigned HOST_WIDE_INT id;
splay_tree_node nd;
void **hash_slot;
@@ -1095,6 +1100,13 @@ create_subid_section_table (void **slot, void *data)
file_data->id = id;
file_data->section_hash_table = lto_obj_create_section_hash_table ();;
lto_splay_tree_insert (file_ids, id, file_data);
+
+ /* Maintain list in linker order */
+ if (!list->first)
+ list->first = file_data;
+ if (list->last)
+ list->last->next = file_data;
+ list->last = file_data;
}
/* Copy section into sub module hash table */
@@ -1129,27 +1141,17 @@ lto_file_finalize (struct lto_file_decl_data *file_data, lto_file *file)
lto_free_section_data (file_data, LTO_section_decls, NULL, data, len);
}
-struct lwstate
-{
- lto_file *file;
- struct lto_file_decl_data **file_data;
- int *count;
-};
-
-/* Traverse ids and create a list of file_datas out of it. */
+/* Finalize FILE_DATA in FILE and increase COUNT. */
-static int lto_create_files_from_ids (splay_tree_node node, void *data)
+static int
+lto_create_files_from_ids (lto_file *file, struct lto_file_decl_data *file_data,
+ int *count)
{
- struct lwstate *lw = (struct lwstate *)data;
- struct lto_file_decl_data *file_data = (struct lto_file_decl_data *)node->value;
-
- lto_file_finalize (file_data, lw->file);
+ lto_file_finalize (file_data, file);
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Creating file %s with sub id " HOST_WIDE_INT_PRINT_HEX "\n",
file_data->file_name, file_data->id);
- file_data->next = *lw->file_data;
- *lw->file_data = file_data;
- (*lw->count)++;
+ (*count)++;
return 0;
}
@@ -1166,29 +1168,31 @@ lto_file_read (lto_file *file, FILE *resolution_file, int *count)
struct lto_file_decl_data *file_data = NULL;
splay_tree file_ids;
htab_t section_hash_table;
- struct lwstate state;
-
- section_hash_table = lto_obj_build_section_table (file);
+ struct lto_section_slot *section;
+ struct file_data_list file_list;
+ struct lto_section_list section_list;
+
+ memset (&section_list, 0, sizeof (struct lto_section_list));
+ section_hash_table = lto_obj_build_section_table (file, &section_list);
/* Find all sub modules in the object and put their sections into new hash
tables in a splay tree. */
file_ids = lto_splay_tree_new ();
- htab_traverse (section_hash_table, create_subid_section_table, file_ids);
-
+ memset (&file_list, 0, sizeof (struct file_data_list));
+ for (section = section_list.first; section != NULL; section = section->next)
+ create_subid_section_table (section, file_ids, &file_list);
+
/* Add resolutions to file ids */
lto_resolution_read (file_ids, resolution_file, file);
- /* Finalize each lto file for each submodule in the merged object
- and create list for returning. */
- state.file = file;
- state.file_data = &file_data;
- state.count = count;
- splay_tree_foreach (file_ids, lto_create_files_from_ids, &state);
-
+ /* Finalize each lto file for each submodule in the merged object */
+ for (file_data = file_list.first; file_data != NULL; file_data = file_data->next)
+ lto_create_files_from_ids (file, file_data, count);
+
splay_tree_delete (file_ids);
htab_delete (section_hash_table);
- return file_data;
+ return file_list.first;
}
#if HAVE_MMAP_FILE && HAVE_SYSCONF && defined _SC_PAGE_SIZE
@@ -1233,7 +1237,10 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
{
fd = open (file_data->file_name, O_RDONLY|O_BINARY);
if (fd == -1)
- return NULL;
+ {
+ fatal_error ("Cannot open %s", file_data->file_name);
+ return NULL;
+ }
fd_name = xstrdup (file_data->file_name);
}
@@ -1251,7 +1258,10 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
result = (char *) mmap (NULL, computed_len, PROT_READ, MAP_PRIVATE,
fd, computed_offset);
if (result == MAP_FAILED)
- return NULL;
+ {
+ fatal_error ("Cannot map %s", file_data->file_name);
+ return NULL;
+ }
return result + diff;
#else
@@ -1260,6 +1270,7 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
|| read (fd, result, len) != (ssize_t) len)
{
free (result);
+ fatal_error ("Cannot read %s", file_data->file_name);
result = NULL;
}
#ifdef __MINGW32__
@@ -2427,7 +2438,7 @@ lto_read_all_file_options (void)
file_data = XCNEW (struct lto_file_decl_data);
file_data->file_name = file->filename;
- file_data->section_hash_table = lto_obj_build_section_table (file);
+ file_data->section_hash_table = lto_obj_build_section_table (file, NULL);
lto_read_file_options (file_data);
diff --git a/gcc/lto/lto.h b/gcc/lto/lto.h
index 8110ace2749..43fcca649ea 100644
--- a/gcc/lto/lto.h
+++ b/gcc/lto/lto.h
@@ -43,7 +43,8 @@ extern void lto_read_all_file_options (void);
/* In lto-elf.c or lto-coff.c */
extern lto_file *lto_obj_file_open (const char *filename, bool writable);
extern void lto_obj_file_close (lto_file *file);
-extern htab_t lto_obj_build_section_table (lto_file *file);
+struct lto_section_list;
+extern htab_t lto_obj_build_section_table (lto_file *file, struct lto_section_list *list);
extern htab_t lto_obj_create_section_hash_table (void);
extern void lto_obj_begin_section (const char *name);
extern void lto_obj_append_data (const void *data, size_t len, void *block);
@@ -58,6 +59,13 @@ struct lto_section_slot
const char *name;
intptr_t start;
size_t len;
+ struct lto_section_slot *next;
+};
+
+/* A list of section slots */
+struct lto_section_list
+{
+ struct lto_section_slot *first, *last;
};
int64_t lto_parse_hex (const char *p);
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index 57186ec8710..f2fd445fa06 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -124,8 +124,10 @@ typedef struct ps_insn *ps_insn_ptr;
/* A single instruction in the partial schedule. */
struct ps_insn
{
- /* The corresponding DDG_NODE. */
- ddg_node_ptr node;
+ /* Identifies the instruction to be scheduled. Values smaller than
+ the ddg's num_nodes refer directly to ddg nodes. A value of
+ X - num_nodes refers to register move X. */
+ int id;
/* The (absolute) cycle in which the PS instruction is scheduled.
Same as SCHED_TIME (node). */
@@ -137,6 +139,33 @@ struct ps_insn
};
+/* Information about a register move that has been added to a partial
+ schedule. */
+struct ps_reg_move_info
+{
+ /* The source of the move is defined by the ps_insn with id DEF.
+ The destination is used by the ps_insns with the ids in USES. */
+ int def;
+ sbitmap uses;
+
+ /* The original form of USES' instructions used OLD_REG, but they
+ should now use NEW_REG. */
+ rtx old_reg;
+ rtx new_reg;
+
+ /* The number of consecutive stages that the move occupies. */
+ int num_consecutive_stages;
+
+ /* An instruction that sets NEW_REG to the correct value. The first
+ move associated with DEF will have an rhs of OLD_REG; later moves
+ use the result of the previous move. */
+ rtx insn;
+};
+
+typedef struct ps_reg_move_info ps_reg_move_info;
+DEF_VEC_O (ps_reg_move_info);
+DEF_VEC_ALLOC_O (ps_reg_move_info, heap);
+
/* Holds the partial schedule as an array of II rows. Each entry of the
array points to a linked list of PS_INSNs, which represents the
instructions that are scheduled for that row. */
@@ -148,6 +177,10 @@ struct partial_schedule
/* rows[i] points to linked list of insns scheduled in row i (0<=i<ii). */
ps_insn_ptr *rows;
+ /* All the moves added for this partial schedule. Index X has
+ a ps_insn id of X + g->num_nodes. */
+ VEC (ps_reg_move_info, heap) *reg_moves;
+
/* rows_length[i] holds the number of instructions in the row.
It is used only (as an optimization) to back off quickly from
trying to schedule a node in a full row; that is, to avoid running
@@ -165,17 +198,6 @@ struct partial_schedule
int stage_count; /* The stage count of the partial schedule. */
};
-/* We use this to record all the register replacements we do in
- the kernel so we can undo SMS if it is not profitable. */
-struct undo_replace_buff_elem
-{
- rtx insn;
- rtx orig_reg;
- rtx new_reg;
- struct undo_replace_buff_elem *next;
-};
-
-
static partial_schedule_ptr create_partial_schedule (int ii, ddg_ptr, int history);
static void free_partial_schedule (partial_schedule_ptr);
@@ -183,9 +205,7 @@ static void reset_partial_schedule (partial_schedule_ptr, int new_ii);
void print_partial_schedule (partial_schedule_ptr, FILE *);
static void verify_partial_schedule (partial_schedule_ptr, sbitmap);
static ps_insn_ptr ps_add_node_check_conflicts (partial_schedule_ptr,
- ddg_node_ptr node, int cycle,
- sbitmap must_precede,
- sbitmap must_follow);
+ int, int, sbitmap, sbitmap);
static void rotate_partial_schedule (partial_schedule_ptr, int);
void set_row_column_for_ps (partial_schedule_ptr);
static void ps_insert_empty_row (partial_schedule_ptr, int, sbitmap);
@@ -201,43 +221,27 @@ static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
static void permute_partial_schedule (partial_schedule_ptr, rtx);
static void generate_prolog_epilog (partial_schedule_ptr, struct loop *,
rtx, rtx);
-static void duplicate_insns_of_cycles (partial_schedule_ptr,
- int, int, int, rtx);
static int calculate_stage_count (partial_schedule_ptr, int);
static void calculate_must_precede_follow (ddg_node_ptr, int, int,
int, int, sbitmap, sbitmap, sbitmap);
static int get_sched_window (partial_schedule_ptr, ddg_node_ptr,
sbitmap, int, int *, int *, int *);
-static bool try_scheduling_node_in_cycle (partial_schedule_ptr, ddg_node_ptr,
- int, int, sbitmap, int *, sbitmap,
- sbitmap);
+static bool try_scheduling_node_in_cycle (partial_schedule_ptr, int, int,
+ sbitmap, int *, sbitmap, sbitmap);
static void remove_node_from_ps (partial_schedule_ptr, ps_insn_ptr);
-#define SCHED_ASAP(x) (((node_sched_params_ptr)(x)->aux.info)->asap)
-#define SCHED_TIME(x) (((node_sched_params_ptr)(x)->aux.info)->time)
-#define SCHED_FIRST_REG_MOVE(x) \
- (((node_sched_params_ptr)(x)->aux.info)->first_reg_move)
-#define SCHED_NREG_MOVES(x) \
- (((node_sched_params_ptr)(x)->aux.info)->nreg_moves)
-#define SCHED_ROW(x) (((node_sched_params_ptr)(x)->aux.info)->row)
-#define SCHED_STAGE(x) (((node_sched_params_ptr)(x)->aux.info)->stage)
-#define SCHED_COLUMN(x) (((node_sched_params_ptr)(x)->aux.info)->column)
+#define NODE_ASAP(node) ((node)->aux.count)
+
+#define SCHED_PARAMS(x) VEC_index (node_sched_params, node_sched_param_vec, x)
+#define SCHED_TIME(x) (SCHED_PARAMS (x)->time)
+#define SCHED_ROW(x) (SCHED_PARAMS (x)->row)
+#define SCHED_STAGE(x) (SCHED_PARAMS (x)->stage)
+#define SCHED_COLUMN(x) (SCHED_PARAMS (x)->column)
/* The scheduling parameters held for each node. */
typedef struct node_sched_params
{
- int asap; /* A lower-bound on the absolute scheduling cycle. */
- int time; /* The absolute scheduling cycle (time >= asap). */
-
- /* The following field (first_reg_move) is a pointer to the first
- register-move instruction added to handle the modulo-variable-expansion
- of the register defined by this node. This register-move copies the
- original register defined by the node. */
- rtx first_reg_move;
-
- /* The number of register-move instructions added, immediately preceding
- first_reg_move. */
- int nreg_moves;
+ int time; /* The absolute scheduling cycle. */
int row; /* Holds time % ii. */
int stage; /* Holds time / ii. */
@@ -247,6 +251,9 @@ typedef struct node_sched_params
int column;
} *node_sched_params_ptr;
+typedef struct node_sched_params node_sched_params;
+DEF_VEC_O (node_sched_params);
+DEF_VEC_ALLOC_O (node_sched_params, heap);
/* The following three functions are copied from the current scheduler
code in order to use sched_analyze() for computing the dependencies.
@@ -295,6 +302,49 @@ static struct haifa_sched_info sms_sched_info =
0
};
+/* Partial schedule instruction ID in PS is a register move. Return
+ information about it. */
+static struct ps_reg_move_info *
+ps_reg_move (partial_schedule_ptr ps, int id)
+{
+ gcc_checking_assert (id >= ps->g->num_nodes);
+ return VEC_index (ps_reg_move_info, ps->reg_moves, id - ps->g->num_nodes);
+}
+
+/* Return the rtl instruction that is being scheduled by partial schedule
+ instruction ID, which belongs to schedule PS. */
+static rtx
+ps_rtl_insn (partial_schedule_ptr ps, int id)
+{
+ if (id < ps->g->num_nodes)
+ return ps->g->nodes[id].insn;
+ else
+ return ps_reg_move (ps, id)->insn;
+}
+
+/* Partial schedule instruction ID, which belongs to PS, occured in
+ the original (unscheduled) loop. Return the first instruction
+ in the loop that was associated with ps_rtl_insn (PS, ID).
+ If the instruction had some notes before it, this is the first
+ of those notes. */
+static rtx
+ps_first_note (partial_schedule_ptr ps, int id)
+{
+ gcc_assert (id < ps->g->num_nodes);
+ return ps->g->nodes[id].first_note;
+}
+
+/* Return the number of consecutive stages that are occupied by
+ partial schedule instruction ID in PS. */
+static int
+ps_num_consecutive_stages (partial_schedule_ptr ps, int id)
+{
+ if (id < ps->g->num_nodes)
+ return 1;
+ else
+ return ps_reg_move (ps, id)->num_consecutive_stages;
+}
+
/* Given HEAD and TAIL which are the first and last insns in a loop;
return the register which controls the loop. Return zero if it has
more than one occurrence in the loop besides the control part or the
@@ -395,35 +445,59 @@ res_MII (ddg_ptr g)
}
-/* Points to the array that contains the sched data for each node. */
-static node_sched_params_ptr node_sched_params;
+/* A vector that contains the sched data for each ps_insn. */
+static VEC (node_sched_params, heap) *node_sched_param_vec;
-/* Allocate sched_params for each node and initialize it. Assumes that
- the aux field of each node contain the asap bound (computed earlier),
- and copies it into the sched_params field. */
+/* Allocate sched_params for each node and initialize it. */
static void
set_node_sched_params (ddg_ptr g)
{
- int i;
+ VEC_truncate (node_sched_params, node_sched_param_vec, 0);
+ VEC_safe_grow_cleared (node_sched_params, heap,
+ node_sched_param_vec, g->num_nodes);
+}
- /* Allocate for each node in the DDG a place to hold the "sched_data". */
- /* Initialize ASAP/ALAP/HIGHT to zero. */
- node_sched_params = (node_sched_params_ptr)
- xcalloc (g->num_nodes,
- sizeof (struct node_sched_params));
+/* Make sure that node_sched_param_vec has an entry for every move in PS. */
+static void
+extend_node_sched_params (partial_schedule_ptr ps)
+{
+ VEC_safe_grow_cleared (node_sched_params, heap, node_sched_param_vec,
+ ps->g->num_nodes + VEC_length (ps_reg_move_info,
+ ps->reg_moves));
+}
- /* Set the pointer of the general data of the node to point to the
- appropriate sched_params structure. */
- for (i = 0; i < g->num_nodes; i++)
+/* Update the sched_params (time, row and stage) for node U using the II,
+ the CYCLE of U and MIN_CYCLE.
+ We're not simply taking the following
+ SCHED_STAGE (u) = CALC_STAGE_COUNT (SCHED_TIME (u), min_cycle, ii);
+ because the stages may not be aligned on cycle 0. */
+static void
+update_node_sched_params (int u, int ii, int cycle, int min_cycle)
+{
+ int sc_until_cycle_zero;
+ int stage;
+
+ SCHED_TIME (u) = cycle;
+ SCHED_ROW (u) = SMODULO (cycle, ii);
+
+ /* The calculation of stage count is done adding the number
+ of stages before cycle zero and after cycle zero. */
+ sc_until_cycle_zero = CALC_STAGE_COUNT (-1, min_cycle, ii);
+
+ if (SCHED_TIME (u) < 0)
+ {
+ stage = CALC_STAGE_COUNT (-1, SCHED_TIME (u), ii);
+ SCHED_STAGE (u) = sc_until_cycle_zero - stage;
+ }
+ else
{
- /* Watch out for aliasing problems? */
- node_sched_params[i].asap = g->nodes[i].aux.count;
- g->nodes[i].aux.info = &node_sched_params[i];
+ stage = CALC_STAGE_COUNT (SCHED_TIME (u), 0, ii);
+ SCHED_STAGE (u) = sc_until_cycle_zero + stage - 1;
}
}
static void
-print_node_sched_params (FILE *file, int num_nodes, ddg_ptr g)
+print_node_sched_params (FILE *file, int num_nodes, partial_schedule_ptr ps)
{
int i;
@@ -431,22 +505,170 @@ print_node_sched_params (FILE *file, int num_nodes, ddg_ptr g)
return;
for (i = 0; i < num_nodes; i++)
{
- node_sched_params_ptr nsp = &node_sched_params[i];
- rtx reg_move = nsp->first_reg_move;
- int j;
+ node_sched_params_ptr nsp = SCHED_PARAMS (i);
fprintf (file, "Node = %d; INSN = %d\n", i,
- (INSN_UID (g->nodes[i].insn)));
- fprintf (file, " asap = %d:\n", nsp->asap);
+ INSN_UID (ps_rtl_insn (ps, i)));
+ fprintf (file, " asap = %d:\n", NODE_ASAP (&ps->g->nodes[i]));
fprintf (file, " time = %d:\n", nsp->time);
- fprintf (file, " nreg_moves = %d:\n", nsp->nreg_moves);
- for (j = 0; j < nsp->nreg_moves; j++)
+ fprintf (file, " stage = %d:\n", nsp->stage);
+ }
+}
+
+/* Set SCHED_COLUMN for each instruction in row ROW of PS. */
+static void
+set_columns_for_row (partial_schedule_ptr ps, int row)
+{
+ ps_insn_ptr cur_insn;
+ int column;
+
+ column = 0;
+ for (cur_insn = ps->rows[row]; cur_insn; cur_insn = cur_insn->next_in_row)
+ SCHED_COLUMN (cur_insn->id) = column++;
+}
+
+/* Set SCHED_COLUMN for each instruction in PS. */
+static void
+set_columns_for_ps (partial_schedule_ptr ps)
+{
+ int row;
+
+ for (row = 0; row < ps->ii; row++)
+ set_columns_for_row (ps, row);
+}
+
+/* Try to schedule the move with ps_insn identifier I_REG_MOVE in PS.
+ Its single predecessor has already been scheduled, as has its
+ ddg node successors. (The move may have also another move as its
+ successor, in which case that successor will be scheduled later.)
+
+ The move is part of a chain that satisfies register dependencies
+ between a producing ddg node and various consuming ddg nodes.
+ If some of these dependencies have a distance of 1 (meaning that
+ the use is upward-exposed) then DISTANCE1_USES is nonnull and
+ contains the set of uses with distance-1 dependencies.
+ DISTANCE1_USES is null otherwise.
+
+ MUST_FOLLOW is a scratch bitmap that is big enough to hold
+ all current ps_insn ids.
+
+ Return true on success. */
+static bool
+schedule_reg_move (partial_schedule_ptr ps, int i_reg_move,
+ sbitmap distance1_uses, sbitmap must_follow)
+{
+ unsigned int u;
+ int this_time, this_distance, this_start, this_end, this_latency;
+ int start, end, c, ii;
+ sbitmap_iterator sbi;
+ ps_reg_move_info *move;
+ rtx this_insn;
+ ps_insn_ptr psi;
+
+ move = ps_reg_move (ps, i_reg_move);
+ ii = ps->ii;
+ if (dump_file)
+ {
+ fprintf (dump_file, "Scheduling register move INSN %d; ii = %d"
+ ", min cycle = %d\n\n", INSN_UID (move->insn), ii,
+ PS_MIN_CYCLE (ps));
+ print_rtl_single (dump_file, move->insn);
+ fprintf (dump_file, "\n%11s %11s %5s\n", "start", "end", "time");
+ fprintf (dump_file, "=========== =========== =====\n");
+ }
+
+ start = INT_MIN;
+ end = INT_MAX;
+
+ /* For dependencies of distance 1 between a producer ddg node A
+ and consumer ddg node B, we have a chain of dependencies:
+
+ A --(T,L1,1)--> M1 --(T,L2,0)--> M2 ... --(T,Ln,0)--> B
+
+ where Mi is the ith move. For dependencies of distance 0 between
+ a producer ddg node A and consumer ddg node C, we have a chain of
+ dependencies:
+
+ A --(T,L1',0)--> M1' --(T,L2',0)--> M2' ... --(T,Ln',0)--> C
+
+ where Mi' occupies the same position as Mi but occurs a stage later.
+ We can only schedule each move once, so if we have both types of
+ chain, we model the second as:
+
+ A --(T,L1',1)--> M1 --(T,L2',0)--> M2 ... --(T,Ln',-1)--> C
+
+ First handle the dependencies between the previously-scheduled
+ predecessor and the move. */
+ this_insn = ps_rtl_insn (ps, move->def);
+ this_latency = insn_latency (this_insn, move->insn);
+ this_distance = distance1_uses && move->def < ps->g->num_nodes ? 1 : 0;
+ this_time = SCHED_TIME (move->def) - this_distance * ii;
+ this_start = this_time + this_latency;
+ this_end = this_time + ii;
+ if (dump_file)
+ fprintf (dump_file, "%11d %11d %5d %d --(T,%d,%d)--> %d\n",
+ this_start, this_end, SCHED_TIME (move->def),
+ INSN_UID (this_insn), this_latency, this_distance,
+ INSN_UID (move->insn));
+
+ if (start < this_start)
+ start = this_start;
+ if (end > this_end)
+ end = this_end;
+
+ /* Handle the dependencies between the move and previously-scheduled
+ successors. */
+ EXECUTE_IF_SET_IN_SBITMAP (move->uses, 0, u, sbi)
+ {
+ this_insn = ps_rtl_insn (ps, u);
+ this_latency = insn_latency (move->insn, this_insn);
+ if (distance1_uses && !TEST_BIT (distance1_uses, u))
+ this_distance = -1;
+ else
+ this_distance = 0;
+ this_time = SCHED_TIME (u) + this_distance * ii;
+ this_start = this_time - ii;
+ this_end = this_time - this_latency;
+ if (dump_file)
+ fprintf (dump_file, "%11d %11d %5d %d --(T,%d,%d)--> %d\n",
+ this_start, this_end, SCHED_TIME (u), INSN_UID (move->insn),
+ this_latency, this_distance, INSN_UID (this_insn));
+
+ if (start < this_start)
+ start = this_start;
+ if (end > this_end)
+ end = this_end;
+ }
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "----------- ----------- -----\n");
+ fprintf (dump_file, "%11d %11d %5s %s\n", start, end, "", "(max, min)");
+ }
+
+ sbitmap_zero (must_follow);
+ SET_BIT (must_follow, move->def);
+
+ start = MAX (start, end - (ii - 1));
+ for (c = end; c >= start; c--)
+ {
+ psi = ps_add_node_check_conflicts (ps, i_reg_move, c,
+ move->uses, must_follow);
+ if (psi)
{
- fprintf (file, " reg_move = ");
- print_rtl_single (file, reg_move);
- reg_move = PREV_INSN (reg_move);
+ update_node_sched_params (i_reg_move, ii, c, PS_MIN_CYCLE (ps));
+ if (dump_file)
+ fprintf (dump_file, "\nScheduled register move INSN %d at"
+ " time %d, row %d\n\n", INSN_UID (move->insn), c,
+ SCHED_ROW (i_reg_move));
+ return true;
}
}
+
+ if (dump_file)
+ fprintf (dump_file, "\nNo available slot\n\n");
+
+ return false;
}
/*
@@ -460,22 +682,23 @@ print_node_sched_params (FILE *file, int num_nodes, ddg_ptr g)
nreg_moves = ----------------------------------- + 1 - { dependence.
ii { 1 if not.
*/
-static struct undo_replace_buff_elem *
-generate_reg_moves (partial_schedule_ptr ps, bool rescan)
+static bool
+schedule_reg_moves (partial_schedule_ptr ps)
{
ddg_ptr g = ps->g;
int ii = ps->ii;
int i;
- struct undo_replace_buff_elem *reg_move_replaces = NULL;
for (i = 0; i < g->num_nodes; i++)
{
ddg_node_ptr u = &g->nodes[i];
ddg_edge_ptr e;
int nreg_moves = 0, i_reg_move;
- sbitmap *uses_of_defs;
- rtx last_reg_move;
rtx prev_reg, old_reg;
+ int first_move;
+ int distances[2];
+ sbitmap must_follow;
+ sbitmap distance1_uses;
rtx set = single_set (u->insn);
/* Skip instructions that do not set a register. */
@@ -484,18 +707,21 @@ generate_reg_moves (partial_schedule_ptr ps, bool rescan)
/* Compute the number of reg_moves needed for u, by looking at life
ranges started at u (excluding self-loops). */
+ distances[0] = distances[1] = false;
for (e = u->out; e; e = e->next_out)
if (e->type == TRUE_DEP && e->dest != e->src)
{
- int nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii;
+ int nreg_moves4e = (SCHED_TIME (e->dest->cuid)
+ - SCHED_TIME (e->src->cuid)) / ii;
if (e->distance == 1)
- nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii;
+ nreg_moves4e = (SCHED_TIME (e->dest->cuid)
+ - SCHED_TIME (e->src->cuid) + ii) / ii;
/* If dest precedes src in the schedule of the kernel, then dest
will read before src writes and we can save one reg_copy. */
- if (SCHED_ROW (e->dest) == SCHED_ROW (e->src)
- && SCHED_COLUMN (e->dest) < SCHED_COLUMN (e->src))
+ if (SCHED_ROW (e->dest->cuid) == SCHED_ROW (e->src->cuid)
+ && SCHED_COLUMN (e->dest->cuid) < SCHED_COLUMN (e->src->cuid))
nreg_moves4e--;
if (nreg_moves4e >= 1)
@@ -512,125 +738,105 @@ generate_reg_moves (partial_schedule_ptr ps, bool rescan)
gcc_assert (!autoinc_var_is_used_p (u->insn, e->dest->insn));
}
+ if (nreg_moves4e)
+ {
+ gcc_assert (e->distance < 2);
+ distances[e->distance] = true;
+ }
nreg_moves = MAX (nreg_moves, nreg_moves4e);
}
if (nreg_moves == 0)
continue;
+ /* Create NREG_MOVES register moves. */
+ first_move = VEC_length (ps_reg_move_info, ps->reg_moves);
+ VEC_safe_grow_cleared (ps_reg_move_info, heap, ps->reg_moves,
+ first_move + nreg_moves);
+ extend_node_sched_params (ps);
+
+ /* Record the moves associated with this node. */
+ first_move += ps->g->num_nodes;
+
+ /* Generate each move. */
+ old_reg = prev_reg = SET_DEST (single_set (u->insn));
+ for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
+ {
+ ps_reg_move_info *move = ps_reg_move (ps, first_move + i_reg_move);
+
+ move->def = i_reg_move > 0 ? first_move + i_reg_move - 1 : i;
+ move->uses = sbitmap_alloc (first_move + nreg_moves);
+ move->old_reg = old_reg;
+ move->new_reg = gen_reg_rtx (GET_MODE (prev_reg));
+ move->num_consecutive_stages = distances[0] && distances[1] ? 2 : 1;
+ move->insn = gen_move_insn (move->new_reg, copy_rtx (prev_reg));
+ sbitmap_zero (move->uses);
+
+ prev_reg = move->new_reg;
+ }
+
+ distance1_uses = distances[1] ? sbitmap_alloc (g->num_nodes) : NULL;
+
/* Every use of the register defined by node may require a different
copy of this register, depending on the time the use is scheduled.
- Set a bitmap vector, telling which nodes use each copy of this
- register. */
- uses_of_defs = sbitmap_vector_alloc (nreg_moves, g->num_nodes);
- sbitmap_vector_zero (uses_of_defs, nreg_moves);
+ Record which uses require which move results. */
for (e = u->out; e; e = e->next_out)
if (e->type == TRUE_DEP && e->dest != e->src)
{
- int dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii;
+ int dest_copy = (SCHED_TIME (e->dest->cuid)
+ - SCHED_TIME (e->src->cuid)) / ii;
if (e->distance == 1)
- dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii;
+ dest_copy = (SCHED_TIME (e->dest->cuid)
+ - SCHED_TIME (e->src->cuid) + ii) / ii;
- if (SCHED_ROW (e->dest) == SCHED_ROW (e->src)
- && SCHED_COLUMN (e->dest) < SCHED_COLUMN (e->src))
+ if (SCHED_ROW (e->dest->cuid) == SCHED_ROW (e->src->cuid)
+ && SCHED_COLUMN (e->dest->cuid) < SCHED_COLUMN (e->src->cuid))
dest_copy--;
if (dest_copy)
- SET_BIT (uses_of_defs[dest_copy - 1], e->dest->cuid);
- }
+ {
+ ps_reg_move_info *move;
- /* Now generate the reg_moves, attaching relevant uses to them. */
- SCHED_NREG_MOVES (u) = nreg_moves;
- old_reg = prev_reg = copy_rtx (SET_DEST (single_set (u->insn)));
- /* Insert the reg-moves right before the notes which precede
- the insn they relates to. */
- last_reg_move = u->first_note;
+ move = ps_reg_move (ps, first_move + dest_copy - 1);
+ SET_BIT (move->uses, e->dest->cuid);
+ if (e->distance == 1)
+ SET_BIT (distance1_uses, e->dest->cuid);
+ }
+ }
+ must_follow = sbitmap_alloc (first_move + nreg_moves);
for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
- {
- unsigned int i_use = 0;
- rtx new_reg = gen_reg_rtx (GET_MODE (prev_reg));
- rtx reg_move = gen_move_insn (new_reg, prev_reg);
- sbitmap_iterator sbi;
-
- add_insn_before (reg_move, last_reg_move, NULL);
- last_reg_move = reg_move;
-
- if (!SCHED_FIRST_REG_MOVE (u))
- SCHED_FIRST_REG_MOVE (u) = reg_move;
-
- EXECUTE_IF_SET_IN_SBITMAP (uses_of_defs[i_reg_move], 0, i_use, sbi)
- {
- struct undo_replace_buff_elem *rep;
-
- rep = (struct undo_replace_buff_elem *)
- xcalloc (1, sizeof (struct undo_replace_buff_elem));
- rep->insn = g->nodes[i_use].insn;
- rep->orig_reg = old_reg;
- rep->new_reg = new_reg;
-
- if (! reg_move_replaces)
- reg_move_replaces = rep;
- else
- {
- rep->next = reg_move_replaces;
- reg_move_replaces = rep;
- }
-
- replace_rtx (g->nodes[i_use].insn, old_reg, new_reg);
- if (rescan)
- df_insn_rescan (g->nodes[i_use].insn);
- }
-
- prev_reg = new_reg;
- }
- sbitmap_vector_free (uses_of_defs);
+ if (!schedule_reg_move (ps, first_move + i_reg_move,
+ distance1_uses, must_follow))
+ break;
+ sbitmap_free (must_follow);
+ if (distance1_uses)
+ sbitmap_free (distance1_uses);
+ if (i_reg_move < nreg_moves)
+ return false;
}
- return reg_move_replaces;
+ return true;
}
-/* Free memory allocated for the undo buffer. */
+/* Emit the moves associatied with PS. Apply the substitutions
+ associated with them. */
static void
-free_undo_replace_buff (struct undo_replace_buff_elem *reg_move_replaces)
+apply_reg_moves (partial_schedule_ptr ps)
{
+ ps_reg_move_info *move;
+ int i;
- while (reg_move_replaces)
+ FOR_EACH_VEC_ELT (ps_reg_move_info, ps->reg_moves, i, move)
{
- struct undo_replace_buff_elem *rep = reg_move_replaces;
-
- reg_move_replaces = reg_move_replaces->next;
- free (rep);
- }
-}
-
-/* Update the sched_params (time, row and stage) for node U using the II,
- the CYCLE of U and MIN_CYCLE.
- We're not simply taking the following
- SCHED_STAGE (u) = CALC_STAGE_COUNT (SCHED_TIME (u), min_cycle, ii);
- because the stages may not be aligned on cycle 0. */
-static void
-update_node_sched_params (ddg_node_ptr u, int ii, int cycle, int min_cycle)
-{
- int sc_until_cycle_zero;
- int stage;
-
- SCHED_TIME (u) = cycle;
- SCHED_ROW (u) = SMODULO (cycle, ii);
-
- /* The calculation of stage count is done adding the number
- of stages before cycle zero and after cycle zero. */
- sc_until_cycle_zero = CALC_STAGE_COUNT (-1, min_cycle, ii);
+ unsigned int i_use;
+ sbitmap_iterator sbi;
- if (SCHED_TIME (u) < 0)
- {
- stage = CALC_STAGE_COUNT (-1, SCHED_TIME (u), ii);
- SCHED_STAGE (u) = sc_until_cycle_zero - stage;
- }
- else
- {
- stage = CALC_STAGE_COUNT (SCHED_TIME (u), 0, ii);
- SCHED_STAGE (u) = sc_until_cycle_zero + stage - 1;
+ EXECUTE_IF_SET_IN_SBITMAP (move->uses, 0, i_use, sbi)
+ {
+ replace_rtx (ps->g->nodes[i_use].insn, move->old_reg, move->new_reg);
+ df_insn_rescan (ps->g->nodes[i_use].insn);
+ }
}
}
@@ -647,18 +853,19 @@ reset_sched_times (partial_schedule_ptr ps, int amount)
for (row = 0; row < ii; row++)
for (crr_insn = ps->rows[row]; crr_insn; crr_insn = crr_insn->next_in_row)
{
- ddg_node_ptr u = crr_insn->node;
+ int u = crr_insn->id;
int normalized_time = SCHED_TIME (u) - amount;
int new_min_cycle = PS_MIN_CYCLE (ps) - amount;
if (dump_file)
{
/* Print the scheduling times after the rotation. */
+ rtx insn = ps_rtl_insn (ps, u);
+
fprintf (dump_file, "crr_insn->node=%d (insn id %d), "
- "crr_insn->cycle=%d, min_cycle=%d", crr_insn->node->cuid,
- INSN_UID (crr_insn->node->insn), normalized_time,
- new_min_cycle);
- if (JUMP_P (crr_insn->node->insn))
+ "crr_insn->cycle=%d, min_cycle=%d", u,
+ INSN_UID (insn), normalized_time, new_min_cycle);
+ if (JUMP_P (insn))
fprintf (dump_file, " (branch)");
fprintf (dump_file, "\n");
}
@@ -671,22 +878,6 @@ reset_sched_times (partial_schedule_ptr ps, int amount)
}
}
-/* Set SCHED_COLUMN of each node according to its position in PS. */
-static void
-set_columns_for_ps (partial_schedule_ptr ps)
-{
- int row;
-
- for (row = 0; row < ps->ii; row++)
- {
- ps_insn_ptr cur_insn = ps->rows[row];
- int column = 0;
-
- for (; cur_insn; cur_insn = cur_insn->next_in_row)
- SCHED_COLUMN (cur_insn->node) = column++;
- }
-}
-
/* Permute the insns according to their order in PS, from row 0 to
row ii-1, and position them right before LAST. This schedules
the insns of the loop kernel. */
@@ -699,9 +890,18 @@ permute_partial_schedule (partial_schedule_ptr ps, rtx last)
for (row = 0; row < ii ; row++)
for (ps_ij = ps->rows[row]; ps_ij; ps_ij = ps_ij->next_in_row)
- if (PREV_INSN (last) != ps_ij->node->insn)
- reorder_insns_nobb (ps_ij->node->first_note, ps_ij->node->insn,
- PREV_INSN (last));
+ {
+ rtx insn = ps_rtl_insn (ps, ps_ij->id);
+
+ if (PREV_INSN (last) != insn)
+ {
+ if (ps_ij->id < ps->g->num_nodes)
+ reorder_insns_nobb (ps_first_note (ps, ps_ij->id), insn,
+ PREV_INSN (last));
+ else
+ add_insn_before (insn, last, NULL);
+ }
+ }
}
/* Set bitmaps TMP_FOLLOW and TMP_PRECEDE to MUST_FOLLOW and MUST_PRECEDE
@@ -750,7 +950,7 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
to row ii-1. If they are equal just bail out. */
stage_count = calculate_stage_count (ps, amount);
stage_count_curr =
- calculate_stage_count (ps, SCHED_TIME (g->closing_branch) - (ii - 1));
+ calculate_stage_count (ps, SCHED_TIME (g->closing_branch->cuid) - (ii - 1));
if (stage_count == stage_count_curr)
{
@@ -779,7 +979,7 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
print_partial_schedule (ps, dump_file);
}
- if (SMODULO (SCHED_TIME (g->closing_branch), ii) == ii - 1)
+ if (SMODULO (SCHED_TIME (g->closing_branch->cuid), ii) == ii - 1)
{
ok = true;
goto clear;
@@ -794,7 +994,7 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
{
bool success;
ps_insn_ptr next_ps_i;
- int branch_cycle = SCHED_TIME (g->closing_branch);
+ int branch_cycle = SCHED_TIME (g->closing_branch->cuid);
int row = SMODULO (branch_cycle, ps->ii);
int num_splits = 0;
sbitmap must_precede, must_follow, tmp_precede, tmp_follow;
@@ -850,13 +1050,12 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
branch so we can remove it from it's current cycle. */
for (next_ps_i = ps->rows[row];
next_ps_i; next_ps_i = next_ps_i->next_in_row)
- if (next_ps_i->node->cuid == g->closing_branch->cuid)
+ if (next_ps_i->id == g->closing_branch->cuid)
break;
remove_node_from_ps (ps, next_ps_i);
success =
- try_scheduling_node_in_cycle (ps, g->closing_branch,
- g->closing_branch->cuid, c,
+ try_scheduling_node_in_cycle (ps, g->closing_branch->cuid, c,
sched_nodes, &num_splits,
tmp_precede, tmp_follow);
gcc_assert (num_splits == 0);
@@ -874,8 +1073,7 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
must_precede, branch_cycle, start, end,
step);
success =
- try_scheduling_node_in_cycle (ps, g->closing_branch,
- g->closing_branch->cuid,
+ try_scheduling_node_in_cycle (ps, g->closing_branch->cuid,
branch_cycle, sched_nodes,
&num_splits, tmp_precede,
tmp_follow);
@@ -889,7 +1087,7 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
fprintf (dump_file,
"SMS success in moving branch to cycle %d\n", c);
- update_node_sched_params (g->closing_branch, ii, c,
+ update_node_sched_params (g->closing_branch->cuid, ii, c,
PS_MIN_CYCLE (ps));
ok = true;
}
@@ -905,7 +1103,7 @@ clear:
static void
duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
- int to_stage, int for_prolog, rtx count_reg)
+ int to_stage, rtx count_reg)
{
int row;
ps_insn_ptr ps_ij;
@@ -913,9 +1111,9 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
for (row = 0; row < ps->ii; row++)
for (ps_ij = ps->rows[row]; ps_ij; ps_ij = ps_ij->next_in_row)
{
- ddg_node_ptr u_node = ps_ij->node;
- int j, i_reg_moves;
- rtx reg_move = NULL_RTX;
+ int u = ps_ij->id;
+ int first_u, last_u;
+ rtx u_insn;
/* Do not duplicate any insn which refers to count_reg as it
belongs to the control part.
@@ -923,52 +1121,20 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
be ignored.
TODO: This should be done by analyzing the control part of
the loop. */
- if (reg_mentioned_p (count_reg, u_node->insn)
- || JUMP_P (ps_ij->node->insn))
+ u_insn = ps_rtl_insn (ps, u);
+ if (reg_mentioned_p (count_reg, u_insn)
+ || JUMP_P (u_insn))
continue;
- if (for_prolog)
- {
- /* SCHED_STAGE (u_node) >= from_stage == 0. Generate increasing
- number of reg_moves starting with the second occurrence of
- u_node, which is generated if its SCHED_STAGE <= to_stage. */
- i_reg_moves = to_stage - SCHED_STAGE (u_node) + 1;
- i_reg_moves = MAX (i_reg_moves, 0);
- i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u_node));
-
- /* The reg_moves start from the *first* reg_move backwards. */
- if (i_reg_moves)
- {
- reg_move = SCHED_FIRST_REG_MOVE (u_node);
- for (j = 1; j < i_reg_moves; j++)
- reg_move = PREV_INSN (reg_move);
- }
- }
- else /* It's for the epilog. */
+ first_u = SCHED_STAGE (u);
+ last_u = first_u + ps_num_consecutive_stages (ps, u) - 1;
+ if (from_stage <= last_u && to_stage >= first_u)
{
- /* SCHED_STAGE (u_node) <= to_stage. Generate all reg_moves,
- starting to decrease one stage after u_node no longer occurs;
- that is, generate all reg_moves until
- SCHED_STAGE (u_node) == from_stage - 1. */
- i_reg_moves = SCHED_NREG_MOVES (u_node)
- - (from_stage - SCHED_STAGE (u_node) - 1);
- i_reg_moves = MAX (i_reg_moves, 0);
- i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u_node));
-
- /* The reg_moves start from the *last* reg_move forwards. */
- if (i_reg_moves)
- {
- reg_move = SCHED_FIRST_REG_MOVE (u_node);
- for (j = 1; j < SCHED_NREG_MOVES (u_node); j++)
- reg_move = PREV_INSN (reg_move);
- }
+ if (u < ps->g->num_nodes)
+ duplicate_insn_chain (ps_first_note (ps, u), u_insn);
+ else
+ emit_insn (copy_rtx (PATTERN (u_insn)));
}
-
- for (j = 0; j < i_reg_moves; j++, reg_move = NEXT_INSN (reg_move))
- emit_insn (copy_rtx (PATTERN (reg_move)));
- if (SCHED_STAGE (u_node) >= from_stage
- && SCHED_STAGE (u_node) <= to_stage)
- duplicate_insn_chain (u_node->first_note, u_node->insn);
}
}
@@ -1002,7 +1168,7 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop,
}
for (i = 0; i < last_stage; i++)
- duplicate_insns_of_cycles (ps, 0, i, 1, count_reg);
+ duplicate_insns_of_cycles (ps, 0, i, count_reg);
/* Put the prolog on the entry edge. */
e = loop_preheader_edge (loop);
@@ -1014,7 +1180,7 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop,
start_sequence ();
for (i = 0; i < last_stage; i++)
- duplicate_insns_of_cycles (ps, i + 1, last_stage, 0, count_reg);
+ duplicate_insns_of_cycles (ps, i + 1, last_stage, count_reg);
/* Put the epilogue on the exit edge. */
gcc_assert (single_exit (loop));
@@ -1350,10 +1516,9 @@ sms_schedule (void)
{
rtx head, tail;
rtx count_reg, count_init;
- int mii, rec_mii;
- unsigned stage_count = 0;
+ int mii, rec_mii, stage_count, min_cycle;
HOST_WIDEST_INT loop_count = 0;
- bool opt_sc_p = false;
+ bool opt_sc_p;
if (! (g = g_arr[loop->num]))
continue;
@@ -1430,62 +1595,63 @@ sms_schedule (void)
fprintf (dump_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
rec_mii, mii, maxii);
- /* After sms_order_nodes and before sms_schedule_by_order, to copy over
- ASAP. */
- set_node_sched_params (g);
-
- ps = sms_schedule_by_order (g, mii, maxii, node_order);
-
- if (ps)
+ for (;;)
{
- /* Try to achieve optimized SC by normalizing the partial
- schedule (having the cycles start from cycle zero).
- The branch location must be placed in row ii-1 in the
- final scheduling. If failed, shift all instructions to
- position the branch in row ii-1. */
- opt_sc_p = optimize_sc (ps, g);
- if (opt_sc_p)
- stage_count = calculate_stage_count (ps, 0);
- else
+ set_node_sched_params (g);
+
+ stage_count = 0;
+ opt_sc_p = false;
+ ps = sms_schedule_by_order (g, mii, maxii, node_order);
+
+ if (ps)
{
- /* Bring the branch to cycle ii-1. */
- int amount = SCHED_TIME (g->closing_branch) - (ps->ii - 1);
-
- if (dump_file)
- fprintf (dump_file, "SMS schedule branch at cycle ii-1\n");
-
- stage_count = calculate_stage_count (ps, amount);
+ /* Try to achieve optimized SC by normalizing the partial
+ schedule (having the cycles start from cycle zero).
+ The branch location must be placed in row ii-1 in the
+ final scheduling. If failed, shift all instructions to
+ position the branch in row ii-1. */
+ opt_sc_p = optimize_sc (ps, g);
+ if (opt_sc_p)
+ stage_count = calculate_stage_count (ps, 0);
+ else
+ {
+ /* Bring the branch to cycle ii-1. */
+ int amount = (SCHED_TIME (g->closing_branch->cuid)
+ - (ps->ii - 1));
+
+ if (dump_file)
+ fprintf (dump_file, "SMS schedule branch at cycle ii-1\n");
+
+ stage_count = calculate_stage_count (ps, amount);
+ }
+
+ gcc_assert (stage_count >= 1);
}
-
- gcc_assert (stage_count >= 1);
- PS_STAGE_COUNT (ps) = stage_count;
- }
-
- /* The default value of PARAM_SMS_MIN_SC is 2 as stage count of
- 1 means that there is no interleaving between iterations thus
- we let the scheduling passes do the job in this case. */
- if (stage_count < (unsigned) PARAM_VALUE (PARAM_SMS_MIN_SC)
- || (count_init && (loop_count <= stage_count))
- || (flag_branch_probabilities && (trip_count <= stage_count)))
- {
- if (dump_file)
+
+ /* The default value of PARAM_SMS_MIN_SC is 2 as stage count of
+ 1 means that there is no interleaving between iterations thus
+ we let the scheduling passes do the job in this case. */
+ if (stage_count < PARAM_VALUE (PARAM_SMS_MIN_SC)
+ || (count_init && (loop_count <= stage_count))
+ || (flag_branch_probabilities && (trip_count <= stage_count)))
{
- fprintf (dump_file, "SMS failed... \n");
- fprintf (dump_file, "SMS sched-failed (stage-count=%d, loop-count=", stage_count);
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, loop_count);
- fprintf (dump_file, ", trip-count=");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, trip_count);
- fprintf (dump_file, ")\n");
+ if (dump_file)
+ {
+ fprintf (dump_file, "SMS failed... \n");
+ fprintf (dump_file, "SMS sched-failed (stage-count=%d,"
+ " loop-count=", stage_count);
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, loop_count);
+ fprintf (dump_file, ", trip-count=");
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, trip_count);
+ fprintf (dump_file, ")\n");
+ }
+ break;
}
- }
- else
- {
- struct undo_replace_buff_elem *reg_move_replaces;
if (!opt_sc_p)
{
/* Rotate the partial schedule to have the branch in row ii-1. */
- int amount = SCHED_TIME (g->closing_branch) - (ps->ii - 1);
+ int amount = SCHED_TIME (g->closing_branch->cuid) - (ps->ii - 1);
reset_sched_times (ps, amount);
rotate_partial_schedule (ps, amount);
@@ -1493,6 +1659,29 @@ sms_schedule (void)
set_columns_for_ps (ps);
+ min_cycle = PS_MIN_CYCLE (ps) - SMODULO (PS_MIN_CYCLE (ps), ps->ii);
+ if (!schedule_reg_moves (ps))
+ {
+ mii = ps->ii + 1;
+ free_partial_schedule (ps);
+ continue;
+ }
+
+ /* Moves that handle incoming values might have been added
+ to a new first stage. Bump the stage count if so.
+
+ ??? Perhaps we could consider rotating the schedule here
+ instead? */
+ if (PS_MIN_CYCLE (ps) < min_cycle)
+ {
+ reset_sched_times (ps, 0);
+ stage_count++;
+ }
+
+ /* The stage count should now be correct without rotation. */
+ gcc_checking_assert (stage_count == calculate_stage_count (ps, 0));
+ PS_STAGE_COUNT (ps) = stage_count;
+
canon_loop (loop);
if (dump_file)
@@ -1531,17 +1720,16 @@ sms_schedule (void)
/* The life-info is not valid any more. */
df_set_bb_dirty (g->bb);
- reg_move_replaces = generate_reg_moves (ps, true);
+ apply_reg_moves (ps);
if (dump_file)
- print_node_sched_params (dump_file, g->num_nodes, g);
+ print_node_sched_params (dump_file, g->num_nodes, ps);
/* Generate prolog and epilog. */
generate_prolog_epilog (ps, loop, count_reg, count_init);
-
- free_undo_replace_buff (reg_move_replaces);
+ break;
}
free_partial_schedule (ps);
- free (node_sched_params);
+ VEC_free (node_sched_params, heap, node_sched_param_vec);
free (node_order);
free_ddg (g);
}
@@ -1622,7 +1810,11 @@ sms_schedule (void)
41. endif
42. compute epilogue & prologue
43. finish - succeeded to schedule
-*/
+
+ ??? The algorithm restricts the scheduling window to II cycles.
+ In rare cases, it may be better to allow windows of II+1 cycles.
+ The window would then start and end on the same row, but with
+ different "must precede" and "must follow" requirements. */
/* A limit on the number of cycles that resource conflicts can span. ??? Should
be provided by DFA, and be dependent on the type of insn scheduled. Currently
@@ -1688,11 +1880,11 @@ get_sched_window (partial_schedule_ptr ps, ddg_node_ptr u_node,
if (psp_not_empty)
for (e = u_node->in; e != 0; e = e->next_in)
{
- ddg_node_ptr v_node = e->src;
+ int v = e->src->cuid;
- if (TEST_BIT (sched_nodes, v_node->cuid))
+ if (TEST_BIT (sched_nodes, v))
{
- int p_st = SCHED_TIME (v_node);
+ int p_st = SCHED_TIME (v);
int earliest = p_st + e->latency - (e->distance * ii);
int latest = (e->data_type == MEM_DEP ? p_st + ii - 1 : INT_MAX);
@@ -1716,11 +1908,11 @@ get_sched_window (partial_schedule_ptr ps, ddg_node_ptr u_node,
if (pss_not_empty)
for (e = u_node->out; e != 0; e = e->next_out)
{
- ddg_node_ptr v_node = e->dest;
+ int v = e->dest->cuid;
- if (TEST_BIT (sched_nodes, v_node->cuid))
+ if (TEST_BIT (sched_nodes, v))
{
- int s_st = SCHED_TIME (v_node);
+ int s_st = SCHED_TIME (v);
int earliest = (e->data_type == MEM_DEP ? s_st - ii + 1 : INT_MIN);
int latest = s_st - e->latency + (e->distance * ii);
@@ -1751,7 +1943,7 @@ get_sched_window (partial_schedule_ptr ps, ddg_node_ptr u_node,
/* Get a target scheduling window no bigger than ii. */
if (early_start == INT_MIN && late_start == INT_MAX)
- early_start = SCHED_ASAP (u_node);
+ early_start = NODE_ASAP (u_node);
else if (early_start == INT_MIN)
early_start = late_start - (ii - 1);
late_start = MIN (late_start, early_start + (ii - 1));
@@ -1848,7 +2040,7 @@ calculate_must_precede_follow (ddg_node_ptr u_node, int start, int end,
SCHED_TIME (e->src) - (e->distance * ii) == first_cycle_in_window */
for (e = u_node->in; e != 0; e = e->next_in)
if (TEST_BIT (sched_nodes, e->src->cuid)
- && ((SCHED_TIME (e->src) - (e->distance * ii)) ==
+ && ((SCHED_TIME (e->src->cuid) - (e->distance * ii)) ==
first_cycle_in_window))
{
if (dump_file)
@@ -1873,7 +2065,7 @@ calculate_must_precede_follow (ddg_node_ptr u_node, int start, int end,
SCHED_TIME (e->dest) + (e->distance * ii) == last_cycle_in_window */
for (e = u_node->out; e != 0; e = e->next_out)
if (TEST_BIT (sched_nodes, e->dest->cuid)
- && ((SCHED_TIME (e->dest) + (e->distance * ii)) ==
+ && ((SCHED_TIME (e->dest->cuid) + (e->distance * ii)) ==
last_cycle_in_window))
{
if (dump_file)
@@ -1897,7 +2089,7 @@ calculate_must_precede_follow (ddg_node_ptr u_node, int start, int end,
last row of the scheduling window) */
static bool
-try_scheduling_node_in_cycle (partial_schedule_ptr ps, ddg_node_ptr u_node,
+try_scheduling_node_in_cycle (partial_schedule_ptr ps,
int u, int cycle, sbitmap sched_nodes,
int *num_splits, sbitmap must_precede,
sbitmap must_follow)
@@ -1906,11 +2098,10 @@ try_scheduling_node_in_cycle (partial_schedule_ptr ps, ddg_node_ptr u_node,
bool success = 0;
verify_partial_schedule (ps, sched_nodes);
- psi = ps_add_node_check_conflicts (ps, u_node, cycle,
- must_precede, must_follow);
+ psi = ps_add_node_check_conflicts (ps, u, cycle, must_precede, must_follow);
if (psi)
{
- SCHED_TIME (u_node) = cycle;
+ SCHED_TIME (u) = cycle;
SET_BIT (sched_nodes, u);
success = 1;
*num_splits = 0;
@@ -1990,7 +2181,7 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
&tmp_precede, must_precede,
c, start, end, step);
success =
- try_scheduling_node_in_cycle (ps, u_node, u, c,
+ try_scheduling_node_in_cycle (ps, u, c,
sched_nodes,
&num_splits, tmp_precede,
tmp_follow);
@@ -2090,7 +2281,7 @@ ps_insert_empty_row (partial_schedule_ptr ps, int split_row,
for (crr_insn = rows_new[row];
crr_insn; crr_insn = crr_insn->next_in_row)
{
- ddg_node_ptr u = crr_insn->node;
+ int u = crr_insn->id;
int new_time = SCHED_TIME (u) + (SCHED_TIME (u) / ii);
SCHED_TIME (u) = new_time;
@@ -2111,7 +2302,7 @@ ps_insert_empty_row (partial_schedule_ptr ps, int split_row,
for (crr_insn = rows_new[row + 1];
crr_insn; crr_insn = crr_insn->next_in_row)
{
- ddg_node_ptr u = crr_insn->node;
+ int u = crr_insn->id;
int new_time = SCHED_TIME (u) + (SCHED_TIME (u) / ii) + 1;
SCHED_TIME (u) = new_time;
@@ -2151,24 +2342,24 @@ compute_split_row (sbitmap sched_nodes, int low, int up, int ii,
{
ddg_edge_ptr e;
int lower = INT_MIN, upper = INT_MAX;
- ddg_node_ptr crit_pred = NULL;
- ddg_node_ptr crit_succ = NULL;
+ int crit_pred = -1;
+ int crit_succ = -1;
int crit_cycle;
for (e = u_node->in; e != 0; e = e->next_in)
{
- ddg_node_ptr v_node = e->src;
+ int v = e->src->cuid;
- if (TEST_BIT (sched_nodes, v_node->cuid)
- && (low == SCHED_TIME (v_node) + e->latency - (e->distance * ii)))
- if (SCHED_TIME (v_node) > lower)
+ if (TEST_BIT (sched_nodes, v)
+ && (low == SCHED_TIME (v) + e->latency - (e->distance * ii)))
+ if (SCHED_TIME (v) > lower)
{
- crit_pred = v_node;
- lower = SCHED_TIME (v_node);
+ crit_pred = v;
+ lower = SCHED_TIME (v);
}
}
- if (crit_pred != NULL)
+ if (crit_pred >= 0)
{
crit_cycle = SCHED_TIME (crit_pred) + 1;
return SMODULO (crit_cycle, ii);
@@ -2176,17 +2367,18 @@ compute_split_row (sbitmap sched_nodes, int low, int up, int ii,
for (e = u_node->out; e != 0; e = e->next_out)
{
- ddg_node_ptr v_node = e->dest;
- if (TEST_BIT (sched_nodes, v_node->cuid)
- && (up == SCHED_TIME (v_node) - e->latency + (e->distance * ii)))
- if (SCHED_TIME (v_node) < upper)
+ int v = e->dest->cuid;
+
+ if (TEST_BIT (sched_nodes, v)
+ && (up == SCHED_TIME (v) - e->latency + (e->distance * ii)))
+ if (SCHED_TIME (v) < upper)
{
- crit_succ = v_node;
- upper = SCHED_TIME (v_node);
+ crit_succ = v;
+ upper = SCHED_TIME (v);
}
}
- if (crit_succ != NULL)
+ if (crit_succ >= 0)
{
crit_cycle = SCHED_TIME (crit_succ);
return SMODULO (crit_cycle, ii);
@@ -2210,10 +2402,10 @@ verify_partial_schedule (partial_schedule_ptr ps, sbitmap sched_nodes)
for (crr_insn = ps->rows[row]; crr_insn; crr_insn = crr_insn->next_in_row)
{
- ddg_node_ptr u = crr_insn->node;
+ int u = crr_insn->id;
length++;
- gcc_assert (TEST_BIT (sched_nodes, u->cuid));
+ gcc_assert (TEST_BIT (sched_nodes, u));
/* ??? Test also that all nodes of sched_nodes are in ps, perhaps by
popcount (sched_nodes) == number of insns in ps. */
gcc_assert (SCHED_TIME (u) >= ps->min_cycle);
@@ -2628,6 +2820,7 @@ create_partial_schedule (int ii, ddg_ptr g, int history)
partial_schedule_ptr ps = XNEW (struct partial_schedule);
ps->rows = (ps_insn_ptr *) xcalloc (ii, sizeof (ps_insn_ptr));
ps->rows_length = (int *) xcalloc (ii, sizeof (int));
+ ps->reg_moves = NULL;
ps->ii = ii;
ps->history = history;
ps->min_cycle = INT_MAX;
@@ -2662,8 +2855,16 @@ free_ps_insns (partial_schedule_ptr ps)
static void
free_partial_schedule (partial_schedule_ptr ps)
{
+ ps_reg_move_info *move;
+ unsigned int i;
+
if (!ps)
return;
+
+ FOR_EACH_VEC_ELT (ps_reg_move_info, ps->reg_moves, i, move)
+ sbitmap_free (move->uses);
+ VEC_free (ps_reg_move_info, heap, ps->reg_moves);
+
free_ps_insns (ps);
free (ps->rows);
free (ps->rows_length);
@@ -2705,12 +2906,12 @@ print_partial_schedule (partial_schedule_ptr ps, FILE *dump)
fprintf (dump, "\n[ROW %d ]: ", i);
while (ps_i)
{
- if (JUMP_P (ps_i->node->insn))
- fprintf (dump, "%d (branch), ",
- INSN_UID (ps_i->node->insn));
+ rtx insn = ps_rtl_insn (ps, ps_i->id);
+
+ if (JUMP_P (insn))
+ fprintf (dump, "%d (branch), ", INSN_UID (insn));
else
- fprintf (dump, "%d, ",
- INSN_UID (ps_i->node->insn));
+ fprintf (dump, "%d, ", INSN_UID (insn));
ps_i = ps_i->next_in_row;
}
@@ -2719,11 +2920,11 @@ print_partial_schedule (partial_schedule_ptr ps, FILE *dump)
/* Creates an object of PS_INSN and initializes it to the given parameters. */
static ps_insn_ptr
-create_ps_insn (ddg_node_ptr node, int cycle)
+create_ps_insn (int id, int cycle)
{
ps_insn_ptr ps_i = XNEW (struct ps_insn);
- ps_i->node = node;
+ ps_i->id = id;
ps_i->next_in_row = NULL;
ps_i->prev_in_row = NULL;
ps_i->cycle = cycle;
@@ -2788,10 +2989,11 @@ ps_insn_find_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
next_ps_i;
next_ps_i = next_ps_i->next_in_row)
{
- if (must_follow && TEST_BIT (must_follow, next_ps_i->node->cuid)
+ if (must_follow
+ && TEST_BIT (must_follow, next_ps_i->id)
&& ! first_must_follow)
first_must_follow = next_ps_i;
- if (must_precede && TEST_BIT (must_precede, next_ps_i->node->cuid))
+ if (must_precede && TEST_BIT (must_precede, next_ps_i->id))
{
/* If we have already met a node that must follow, then
there is no possible column. */
@@ -2802,8 +3004,8 @@ ps_insn_find_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
}
/* The closing branch must be the last in the row. */
if (must_precede
- && TEST_BIT (must_precede, next_ps_i->node->cuid)
- && JUMP_P (next_ps_i->node->insn))
+ && TEST_BIT (must_precede, next_ps_i->id)
+ && JUMP_P (ps_rtl_insn (ps, next_ps_i->id)))
return false;
last_in_row = next_ps_i;
@@ -2812,7 +3014,7 @@ ps_insn_find_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
/* The closing branch is scheduled as well. Make sure there is no
dependent instruction after it as the branch should be the last
instruction in the row. */
- if (JUMP_P (ps_i->node->insn))
+ if (JUMP_P (ps_rtl_insn (ps, ps_i->id)))
{
if (first_must_follow)
return false;
@@ -2863,7 +3065,6 @@ ps_insn_advance_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
{
ps_insn_ptr prev, next;
int row;
- ddg_node_ptr next_node;
if (!ps || !ps_i)
return false;
@@ -2873,11 +3074,9 @@ ps_insn_advance_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
if (! ps_i->next_in_row)
return false;
- next_node = ps_i->next_in_row->node;
-
/* Check if next_in_row is dependent on ps_i, both having same sched
times (typically ANTI_DEP). If so, ps_i cannot skip over it. */
- if (must_follow && TEST_BIT (must_follow, next_node->cuid))
+ if (must_follow && TEST_BIT (must_follow, ps_i->next_in_row->id))
return false;
/* Advance PS_I over its next_in_row in the doubly linked list. */
@@ -2908,7 +3107,7 @@ ps_insn_advance_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
before/after (respectively) the node pointed to by PS_I when scheduled
in the same cycle. */
static ps_insn_ptr
-add_node_to_ps (partial_schedule_ptr ps, ddg_node_ptr node, int cycle,
+add_node_to_ps (partial_schedule_ptr ps, int id, int cycle,
sbitmap must_precede, sbitmap must_follow)
{
ps_insn_ptr ps_i;
@@ -2917,7 +3116,7 @@ add_node_to_ps (partial_schedule_ptr ps, ddg_node_ptr node, int cycle,
if (ps->rows_length[row] >= issue_rate)
return NULL;
- ps_i = create_ps_insn (node, cycle);
+ ps_i = create_ps_insn (id, cycle);
/* Finds and inserts PS_I according to MUST_FOLLOW and
MUST_PRECEDE. */
@@ -2969,7 +3168,7 @@ ps_has_conflicts (partial_schedule_ptr ps, int from, int to)
crr_insn;
crr_insn = crr_insn->next_in_row)
{
- rtx insn = crr_insn->node->insn;
+ rtx insn = ps_rtl_insn (ps, crr_insn->id);
if (!NONDEBUG_INSN_P (insn))
continue;
@@ -3006,7 +3205,7 @@ ps_has_conflicts (partial_schedule_ptr ps, int from, int to)
cuid N must be come before/after (respectively) the node pointed to by
PS_I when scheduled in the same cycle. */
ps_insn_ptr
-ps_add_node_check_conflicts (partial_schedule_ptr ps, ddg_node_ptr n,
+ps_add_node_check_conflicts (partial_schedule_ptr ps, int n,
int c, sbitmap must_precede,
sbitmap must_follow)
{
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index c31ba7fb6a6..6e32f5f4b8a 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,73 @@
+2011-10-18 Mikael Pettersson <mikpe@it.uu.se>
+
+ PR objc/50743
+ * objc-act.c (check_duplicates): Cast TREE_VEC_LENGTH result to
+ size_t to avoid signed/unsigned
+ comparison.
+ (insert_method_into_method_map): Likewise.
+
+2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * objc-map.h: New file.
+ * objc-map.c: New file.
+ * config-lang.in (gtfiles): Added objc-map.h.
+ * Make-lang.in (OBJC_OBJS): Added objc-map.o.
+ (objc/objc-map.o): New rule.
+ (objc/objc-act.o): Depend on objc/objc-map.h.
+ * objc-next-runtime-abi-02.c: Added a TODO comment.
+ * objc-act.c: Include objc-map.h.
+ (nst_method_hash_list, cls_method_hash_list): Removed.
+ (instance_method_map, class_method_map): New.
+ (cls_name_hash_list, als_name_hash_list): Removed.
+ (class_name_map, alias_name_map): Removed.
+ (ivar_offset_hash_list): Removed.
+ (hash_class_name_enter, hash_class_name_lookup, hash_enter,
+ hash_lookup, hash_add_attr, add_method_to_hash_list): Removed.
+ (interface_hash_init): New.
+ (objc_init): Call interface_hash_init.
+ (objc_write_global_declarations): Iterate over class_method_map
+ and instance_method_map instead of cls_method_hash_list and
+ nst_method_hash_list.
+ (objc_declare_alias): Use alias_name_map instead of
+ cls_name_hash_list.
+ (objc_is_class_name): Use class_name_map and alias_name_map
+ instead of cls_name_hash_list and als_name_hash_list.
+ (interface_tuple, interface_htab, hash_interface, eq_interface):
+ Removed.
+ (interface_map): New.
+ (add_class): Renamed to add_interface. Use interface_map instead
+ of interface_htab.
+ (lookup_interface): Use interface_map instead of interface_htab.
+ (check_duplicates): Changed first argument to be a tree,
+ potentially a TREE_VEC, instead of a hash. Changed implementation
+ to match.
+ (lookup_method_in_hash_lists): Use class_method_map and
+ instance_method_map instead of cls_method_hash_list and
+ nst_method_hash_list.
+ (objc_build_selector_expr): Likewise.
+ (hash_func): Removed.
+ (hash_init): Create instance_method_map, class_method_map,
+ class_name_map, and alias_name_map. Do not create
+ nst_method_hash_list, cls_method_hash_list, cls_name_hash_list,
+ als_name_hash_list, and ivar_offset_hash_list.
+ (insert_method_into_method_map): New.
+ (objc_add_method): Use insert_method_into_method_map instead of
+ add_method_to_hash_list.
+ (start_class): Call add_interface instead of add_class.
+ * objc-act.h (cls_name_hash_list, als_name_hash_list,
+ nst_method_hash_list, cls_method_hash_list): Removed.
+
+2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * objc-next-runtime-abi-01.c (objc_build_exc_ptr): Delete old
+ interface with two parallel arrays to hold standard builtin
+ declarations, and replace it with a function based interface that
+ can support creating builtins on the fly in the future. Change
+ all uses, and poison the old names. Make sure 0 is not a
+ legitimate builtin index.
+ * objc-next-runtime-abi-02.c (objc_build_exc_ptr): Ditto.
+ * objc-gnu-runtime-abi-01.c (objc_build_exc_ptr): Ditto.
+
2011-07-19 Richard Guenther <rguenther@suse.de>
* objc-next-runtime-abi-02.c (objc_v2_build_ivar_ref):
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index f9b3907fe1c..5cca11a6b4d 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -55,7 +55,8 @@ OBJC_OBJS = objc/objc-lang.o objc/objc-act.o \
objc/objc-gnu-runtime-abi-01.o \
objc/objc-next-runtime-abi-01.o \
objc/objc-next-runtime-abi-02.o \
- objc/objc-encoding.o
+ objc/objc-encoding.o \
+ objc/objc-map.o
objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
@@ -129,6 +130,7 @@ objc/objc-act.o : objc/objc-act.c \
$(HASHTAB_H) $(GIMPLE_H) \
$(C_PRAGMA_H) $(C_TARGET_H) \
objc/objc-encoding.h \
+ objc/objc-map.h \
objc/objc-runtime-hooks.h \
objc/objc-runtime-shared-support.h
@@ -139,6 +141,12 @@ objc/objc-encoding.o : objc/objc-encoding.c \
objc/objc-encoding.h \
objc/objc-runtime-shared-support.h
+objc/objc-map.o : objc/objc-map.c \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ objc/objc-map.h
+
objc.srcextra:
#
diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in
index 0de0650c0de..48f8582d74c 100644
--- a/gcc/objc/config-lang.in
+++ b/gcc/objc/config-lang.in
@@ -36,4 +36,4 @@ lang_requires="c"
# Order is important. If you change this list, make sure you test
# building without C++ as well; that is, remove the gcc/cp directory,
# and build with --enable-languages=c,objc.
-gtfiles="\$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
+gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 72a486d9c83..9690113862e 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "langhooks.h"
#include "objc-act.h"
+#include "objc-map.h"
#include "input.h"
#include "function.h"
#include "output.h"
@@ -157,27 +158,25 @@ static void objc_generate_cxx_cdtors (void);
static void objc_decl_method_attributes (tree*, tree, int);
static tree build_keyword_selector (tree);
-/* Hash tables to manage the global pool of method prototypes. */
static void hash_init (void);
-hash *nst_method_hash_list = 0;
-hash *cls_method_hash_list = 0;
+/* Hash tables to manage the global pool of method prototypes. Each
+ of these maps map a method name (selector) identifier to either a
+ single tree (for methods with a single method prototype) or a
+ TREE_VEC (for methods with multiple method prototypes). */
+static GTY(()) objc_map_t instance_method_map = 0;
+static GTY(()) objc_map_t class_method_map = 0;
/* Hash tables to manage the global pool of class names. */
-hash *cls_name_hash_list = 0;
-hash *als_name_hash_list = 0;
+static GTY(()) objc_map_t class_name_map = 0;
+static GTY(()) objc_map_t alias_name_map = 0;
-hash *ivar_offset_hash_list = 0;
-
-static void hash_class_name_enter (hash *, tree, tree);
-static hash hash_class_name_lookup (hash *, tree);
-
-static hash hash_lookup (hash *, tree);
static tree lookup_method (tree, tree);
static tree lookup_method_static (tree, tree, int);
-static tree add_class (tree, tree);
+static void interface_hash_init (void);
+static tree add_interface (tree, tree);
static void add_category (tree, tree);
static inline tree lookup_category (tree, tree);
@@ -207,7 +206,7 @@ static void generate_struct_by_value_array (void) ATTRIBUTE_NORETURN;
static void mark_referenced_methods (void);
static bool objc_type_valid_for_messaging (tree type, bool allow_classes);
-static tree check_duplicates (hash, int, int);
+static tree check_duplicates (tree, int, int);
/*** Private Interface (data) ***/
/* Flags for lookup_method_static(). */
@@ -380,6 +379,7 @@ objc_init (void)
/* Set up stuff used by FE parser and all runtimes. */
errbuf = XNEWVEC (char, 1024 * 10);
+ interface_hash_init ();
hash_init ();
objc_encoding_init ();
/* ... and then check flags and set-up for the selected runtime ... */
@@ -418,19 +418,15 @@ objc_write_global_declarations (void)
if (warn_selector)
{
- int slot;
- hash hsh;
+ objc_map_iterator_t i;
- /* Run through the selector hash tables and print a warning for any
- selector which has multiple methods. */
+ objc_map_iterator_initialize (class_method_map, &i);
+ while (objc_map_iterator_move_to_next (class_method_map, &i))
+ check_duplicates (objc_map_iterator_current_value (class_method_map, i), 0, 1);
- for (slot = 0; slot < SIZEHASHTABLE; slot++)
- {
- for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0, 1);
- for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0, 0);
- }
+ objc_map_iterator_initialize (instance_method_map, &i);
+ while (objc_map_iterator_move_to_next (instance_method_map, &i))
+ check_duplicates (objc_map_iterator_current_value (instance_method_map, i), 0, 0);
}
/* TODO: consider an early exit here if either errorcount or sorrycount
@@ -3351,8 +3347,7 @@ objc_declare_alias (tree alias_ident, tree class_ident)
#ifdef OBJCPLUS
pop_lang_context ();
#endif
- hash_class_name_enter (als_name_hash_list, alias_ident,
- underlying_class);
+ objc_map_put (alias_name_map, alias_ident, underlying_class);
}
}
@@ -3392,15 +3387,13 @@ objc_declare_class (tree identifier)
the TYPE_OBJC_INTERFACE. If later an @interface is found,
we'll replace the ident with the interface. */
TYPE_OBJC_INTERFACE (record) = identifier;
- hash_class_name_enter (cls_name_hash_list, identifier, NULL_TREE);
+ objc_map_put (class_name_map, identifier, NULL_TREE);
}
}
tree
objc_is_class_name (tree ident)
{
- hash target;
-
if (ident && TREE_CODE (ident) == IDENTIFIER_NODE)
{
tree t = identifier_global_value (ident);
@@ -3428,16 +3421,17 @@ objc_is_class_name (tree ident)
if (lookup_interface (ident))
return ident;
- target = hash_class_name_lookup (cls_name_hash_list, ident);
- if (target)
- return target->key;
+ {
+ tree target;
- target = hash_class_name_lookup (als_name_hash_list, ident);
- if (target)
- {
- gcc_assert (target->list && target->list->value);
- return target->list->value;
- }
+ target = objc_map_get (class_name_map, ident);
+ if (target != OBJC_MAP_NOT_FOUND)
+ return ident;
+
+ target = objc_map_get (alias_name_map, ident);
+ if (target != OBJC_MAP_NOT_FOUND)
+ return target;
+ }
return 0;
}
@@ -3761,25 +3755,30 @@ objc_generate_write_barrier (tree lhs, enum tree_code modifycode, tree rhs)
return result;
}
-struct GTY(()) interface_tuple {
- tree id;
- tree class_name;
-};
+/* Implementation of the table mapping a class name (as an identifier)
+ to a class node. The two public functions for it are
+ lookup_interface() and add_interface(). add_interface() is only
+ used in this file, so we can make it static. */
-static GTY ((param_is (struct interface_tuple))) htab_t interface_htab;
+static GTY(()) objc_map_t interface_map;
-static hashval_t
-hash_interface (const void *p)
+static void
+interface_hash_init (void)
{
- const struct interface_tuple *d = (const struct interface_tuple *) p;
- return IDENTIFIER_HASH_VALUE (d->id);
+ interface_map = objc_map_alloc_ggc (200);
}
-static int
-eq_interface (const void *p1, const void *p2)
+static tree
+add_interface (tree class_name, tree name)
{
- const struct interface_tuple *d = (const struct interface_tuple *) p1;
- return d->id == p2;
+ /* Put interfaces on list in reverse order. */
+ TREE_CHAIN (class_name) = interface_chain;
+ interface_chain = class_name;
+
+ /* Add it to the map. */
+ objc_map_put (interface_map, name, class_name);
+
+ return interface_chain;
}
tree
@@ -3794,19 +3793,12 @@ lookup_interface (tree ident)
return NULL_TREE;
{
- struct interface_tuple **slot;
- tree i = NULL_TREE;
+ tree interface = objc_map_get (interface_map, ident);
- if (interface_htab)
- {
- slot = (struct interface_tuple **)
- htab_find_slot_with_hash (interface_htab, ident,
- IDENTIFIER_HASH_VALUE (ident),
- NO_INSERT);
- if (slot && *slot)
- i = (*slot)->class_name;
- }
- return i;
+ if (interface == OBJC_MAP_NOT_FOUND)
+ return NULL_TREE;
+ else
+ return interface;
}
}
@@ -5052,71 +5044,75 @@ build_function_type_for_method (tree return_type, tree method,
return ftype;
}
+/* The 'method' argument is a tree; this tree could either be a single
+ method, which is returned, or could be a TREE_VEC containing a list
+ of methods. In that case, the first one is returned, and warnings
+ are issued as appropriate. */
static tree
-check_duplicates (hash hsh, int methods, int is_class)
+check_duplicates (tree method, int methods, int is_class)
{
- tree meth = NULL_TREE;
-
- if (hsh)
- {
- meth = hsh->key;
-
- if (hsh->list)
- {
- /* We have two or more methods with the same name but
- different types. */
- attr loop;
-
- /* But just how different are those types? If
- -Wno-strict-selector-match is specified, we shall not
- complain if the differences are solely among types with
- identical size and alignment. */
- if (!warn_strict_selector_match)
- {
- for (loop = hsh->list; loop; loop = loop->next)
- if (!comp_proto_with_proto (meth, loop->value, 0))
- goto issue_warning;
-
- return meth;
- }
-
- issue_warning:
- if (methods)
- {
- bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
-
- warning_at (input_location, 0,
- "multiple methods named %<%c%E%> found",
- (is_class ? '+' : '-'),
- METHOD_SEL_NAME (meth));
- inform (DECL_SOURCE_LOCATION (meth), "using %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (meth)));
- }
- else
- {
- bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
+ tree first_method;
+ size_t i;
- warning_at (input_location, 0,
- "multiple selectors named %<%c%E%> found",
- (is_class ? '+' : '-'),
- METHOD_SEL_NAME (meth));
- inform (DECL_SOURCE_LOCATION (meth), "found %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (meth)));
- }
-
- for (loop = hsh->list; loop; loop = loop->next)
- {
- bool type = TREE_CODE (loop->value) == INSTANCE_METHOD_DECL;
+ if (method == NULL_TREE)
+ return NULL_TREE;
- inform (DECL_SOURCE_LOCATION (loop->value), "also found %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (loop->value)));
- }
- }
+ if (TREE_CODE (method) != TREE_VEC)
+ return method;
+
+ /* We have two or more methods with the same name but different
+ types. */
+ first_method = TREE_VEC_ELT (method, 0);
+
+ /* But just how different are those types? If
+ -Wno-strict-selector-match is specified, we shall not complain if
+ the differences are solely among types with identical size and
+ alignment. */
+ if (!warn_strict_selector_match)
+ {
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (method); i++)
+ if (!comp_proto_with_proto (first_method, TREE_VEC_ELT (method, i), 0))
+ goto issue_warning;
+
+ return first_method;
+ }
+
+ issue_warning:
+ if (methods)
+ {
+ bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL;
+
+ warning_at (input_location, 0,
+ "multiple methods named %<%c%E%> found",
+ (is_class ? '+' : '-'),
+ METHOD_SEL_NAME (first_method));
+ inform (DECL_SOURCE_LOCATION (first_method), "using %<%c%s%>",
+ (type ? '-' : '+'),
+ identifier_to_locale (gen_method_decl (first_method)));
}
- return meth;
+ else
+ {
+ bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL;
+
+ warning_at (input_location, 0,
+ "multiple selectors named %<%c%E%> found",
+ (is_class ? '+' : '-'),
+ METHOD_SEL_NAME (first_method));
+ inform (DECL_SOURCE_LOCATION (first_method), "found %<%c%s%>",
+ (type ? '-' : '+'),
+ identifier_to_locale (gen_method_decl (first_method)));
+ }
+
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (method); i++)
+ {
+ bool type = TREE_CODE (TREE_VEC_ELT (method, i)) == INSTANCE_METHOD_DECL;
+
+ inform (DECL_SOURCE_LOCATION (TREE_VEC_ELT (method, i)), "also found %<%c%s%>",
+ (type ? '-' : '+'),
+ identifier_to_locale (gen_method_decl (TREE_VEC_ELT (method, i))));
+ }
+
+ return first_method;
}
/* If RECEIVER is a class reference, return the identifier node for
@@ -5294,17 +5290,18 @@ objc_build_message_expr (tree receiver, tree message_args)
static tree
lookup_method_in_hash_lists (tree sel_name, int is_class)
{
- hash method_prototype = NULL;
+ tree method_prototype = OBJC_MAP_NOT_FOUND;
if (!is_class)
- method_prototype = hash_lookup (nst_method_hash_list,
- sel_name);
-
- if (!method_prototype)
+ method_prototype = objc_map_get (instance_method_map, sel_name);
+
+ if (method_prototype == OBJC_MAP_NOT_FOUND)
{
- method_prototype = hash_lookup (cls_method_hash_list,
- sel_name);
+ method_prototype = objc_map_get (class_method_map, sel_name);
is_class = 1;
+
+ if (method_prototype == OBJC_MAP_NOT_FOUND)
+ return NULL_TREE;
}
return check_duplicates (method_prototype, 1, is_class);
@@ -5714,21 +5711,19 @@ objc_build_selector_expr (location_t loc, tree selnamelist)
/* Look the selector up in the list of all known class and
instance methods (up to this line) to check that the selector
exists. */
- hash hsh;
+ tree method;
/* First try with instance methods. */
- hsh = hash_lookup (nst_method_hash_list, selname);
+ method = objc_map_get (instance_method_map, selname);
/* If not found, try with class methods. */
- if (!hsh)
+ if (method == OBJC_MAP_NOT_FOUND)
{
- hsh = hash_lookup (cls_method_hash_list, selname);
- }
+ method = objc_map_get (class_method_map, selname);
- /* If still not found, print out a warning. */
- if (!hsh)
- {
- warning (0, "undeclared selector %qE", selname);
+ /* If still not found, print out a warning. */
+ if (method == OBJC_MAP_NOT_FOUND)
+ warning (0, "undeclared selector %qE", selname);
}
}
@@ -5761,131 +5756,99 @@ build_ivar_reference (tree id)
return (*runtime.build_ivar_reference) (input_location, base, id);
}
-/* Compute a hash value for a given method SEL_NAME. */
-
-static size_t
-hash_func (tree sel_name)
-{
- const unsigned char *s
- = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
- size_t h = 0;
-
- while (*s)
- h = h * 67 + *s++ - 113;
- return h;
-}
-
static void
hash_init (void)
{
- nst_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
- cls_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
-
- cls_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
- als_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ instance_method_map = objc_map_alloc_ggc (1000);
+ class_method_map = objc_map_alloc_ggc (1000);
- ivar_offset_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ class_name_map = objc_map_alloc_ggc (200);
+ alias_name_map = objc_map_alloc_ggc (200);
/* Initialize the hash table used to hold the constant string objects. */
string_htab = htab_create_ggc (31, string_hash,
string_eq, NULL);
}
-/* This routine adds sel_name to the hash list. sel_name is a class or alias
- name for the class. If alias name, then value is its underlying class.
- If class, the value is NULL_TREE. */
-
+/* Use the following to add a method to class_method_map or
+ instance_method_map. It will add the method, keyed by the
+ METHOD_SEL_NAME. If the method already exists, but with one or
+ more different prototypes, it will store a TREE_VEC in the map,
+ with the method prototypes in the vector. */
static void
-hash_class_name_enter (hash *hashlist, tree sel_name, tree value)
+insert_method_into_method_map (bool class_method, tree method)
{
- hash obj;
- int slot = hash_func (sel_name) % SIZEHASHTABLE;
+ tree method_name = METHOD_SEL_NAME (method);
+ tree existing_entry;
+ objc_map_t map;
- obj = ggc_alloc_hashed_entry ();
- if (value != NULL_TREE)
- {
- /* Save the underlying class for the 'alias' in the hash table */
- attr obj_attr = ggc_alloc_hashed_attribute ();
- obj_attr->value = value;
- obj->list = obj_attr;
- }
+ if (class_method)
+ map = class_method_map;
else
- obj->list = 0;
- obj->next = hashlist[slot];
- obj->key = sel_name;
-
- hashlist[slot] = obj; /* append to front */
+ map = instance_method_map;
-}
+ /* Check if the method already exists in the map. */
+ existing_entry = objc_map_get (map, method_name);
-/*
- Searches in the hash table looking for a match for class or alias name.
-*/
-
-static hash
-hash_class_name_lookup (hash *hashlist, tree sel_name)
-{
- hash target;
-
- target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
-
- while (target)
+ /* If not, we simply add it to the map. */
+ if (existing_entry == OBJC_MAP_NOT_FOUND)
+ objc_map_put (map, method_name, method);
+ else
{
- if (sel_name == target->key)
- return target;
-
- target = target->next;
- }
- return 0;
-}
-
-/* WARNING!!!! hash_enter is called with a method, and will peek
- inside to find its selector! But hash_lookup is given a selector
- directly, and looks for the selector that's inside the found
- entry's key (method) for comparison. */
-
-static void
-hash_enter (hash *hashlist, tree method)
-{
- hash obj;
- int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
-
- obj = ggc_alloc_hashed_entry ();
- obj->list = 0;
- obj->next = hashlist[slot];
- obj->key = method;
-
- hashlist[slot] = obj; /* append to front */
-}
-
-static hash
-hash_lookup (hash *hashlist, tree sel_name)
-{
- hash target;
+ tree new_entry;
+
+ /* If an entry already exists, it's more complicated. We'll
+ have to check whether the method prototype is the same or
+ not. */
+ if (TREE_CODE (existing_entry) != TREE_VEC)
+ {
+ /* If the method prototypes are the same, there is nothing
+ to do. */
+ if (comp_proto_with_proto (method, existing_entry, 1))
+ return;
- target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
+ /* If not, create a vector to store both the method already
+ in the map, and the new one that we are adding. */
+ new_entry = make_tree_vec (2);
+
+ TREE_VEC_ELT (new_entry, 0) = existing_entry;
+ TREE_VEC_ELT (new_entry, 1) = method;
+ }
+ else
+ {
+ /* An entry already exists, and it's already a vector. This
+ means that at least 2 different method prototypes were
+ already found, and we're considering registering yet
+ another one. */
+ size_t i;
+
+ /* Check all the existing prototypes. If any matches the
+ one we need to add, there is nothing to do because it's
+ already there. */
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (existing_entry); i++)
+ if (comp_proto_with_proto (method, TREE_VEC_ELT (existing_entry, i), 1))
+ return;
- while (target)
- {
- if (sel_name == METHOD_SEL_NAME (target->key))
- return target;
+ /* Else, create a new, bigger vector and add the new method
+ at the end of it. This is inefficient but extremely
+ rare; in any sane program most methods have a single
+ prototype, and very few, if any, will have more than
+ 2! */
+ new_entry = make_tree_vec (TREE_VEC_LENGTH (existing_entry) + 1);
+
+ /* Copy the methods from the existing vector. */
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (existing_entry); i++)
+ TREE_VEC_ELT (new_entry, i) = TREE_VEC_ELT (existing_entry, i);
+
+ /* Add the new method at the end. */
+ TREE_VEC_ELT (new_entry, i) = method;
+ }
- target = target->next;
+ /* Store the new vector in the map. */
+ objc_map_put (map, method_name, new_entry);
}
- return 0;
}
-static void
-hash_add_attr (hash entry, tree value)
-{
- attr obj;
-
- obj = ggc_alloc_hashed_attribute ();
- obj->next = entry->list;
- obj->value = value;
-
- entry->list = obj; /* append to front */
-}
static tree
lookup_method (tree mchain, tree method)
@@ -5988,31 +5951,6 @@ lookup_method_static (tree interface, tree ident, int flags)
}
}
-/* Add the method to the hash list if it doesn't contain an identical
- method already. */
-
-static void
-add_method_to_hash_list (hash *hash_list, tree method)
-{
- hash hsh;
-
- if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
- {
- /* Install on a global chain. */
- hash_enter (hash_list, method);
- }
- else
- {
- /* Check types against those; if different, add to a list. */
- attr loop;
- int already_there = comp_proto_with_proto (method, hsh->key, 1);
- for (loop = hsh->list; !already_there && loop; loop = loop->next)
- already_there |= comp_proto_with_proto (method, loop->value, 1);
- if (!already_there)
- hash_add_attr (hsh, method);
- }
-}
-
static tree
objc_add_method (tree klass, tree method, int is_class, bool is_optional)
{
@@ -6135,10 +6073,10 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional)
}
if (is_class)
- add_method_to_hash_list (cls_method_hash_list, method);
+ insert_method_into_method_map (true, method);
else
{
- add_method_to_hash_list (nst_method_hash_list, method);
+ insert_method_into_method_map (false, method);
/* Instance methods in root classes (and categories thereof)
may act as class methods as a last resort. We also add
@@ -6151,37 +6089,12 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional)
if (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE
|| !CLASS_SUPER_NAME (klass))
- add_method_to_hash_list (cls_method_hash_list, method);
+ insert_method_into_method_map (true, method);
}
return method;
}
-static tree
-add_class (tree class_name, tree name)
-{
- struct interface_tuple **slot;
-
- /* Put interfaces on list in reverse order. */
- TREE_CHAIN (class_name) = interface_chain;
- interface_chain = class_name;
-
- if (interface_htab == NULL)
- interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL);
- slot = (struct interface_tuple **)
- htab_find_slot_with_hash (interface_htab, name,
- IDENTIFIER_HASH_VALUE (name),
- INSERT);
- if (!*slot)
- {
- *slot = ggc_alloc_cleared_interface_tuple ();
- (*slot)->id = name;
- }
- (*slot)->class_name = class_name;
-
- return interface_chain;
-}
-
static void
add_category (tree klass, tree category)
{
@@ -6951,8 +6864,8 @@ start_class (enum tree_code code, tree class_name, tree super_name,
{
warning (0, "cannot find interface declaration for %qE",
class_name);
- add_class (implementation_template = objc_implementation_context,
- class_name);
+ add_interface (implementation_template = objc_implementation_context,
+ class_name);
}
/* If a super class has been specified in the implementation,
@@ -6985,7 +6898,7 @@ start_class (enum tree_code code, tree class_name, tree super_name,
warning (0, "duplicate interface declaration for class %qE", class_name);
#endif
else
- add_class (klass, class_name);
+ add_interface (klass, class_name);
if (protocol_list)
CLASS_PROTOCOL_LIST (klass)
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 33f90fdb785..e958e669af0 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -252,12 +252,6 @@ struct GTY(()) hashed_entry {
#define SIZEHASHTABLE 257
-extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list;
-extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_method_hash_list;
-
-extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_name_hash_list;
-extern GTY ((length ("SIZEHASHTABLE"))) hash *als_name_hash_list;
-
/* An array of all the local variables in the current function that
need to be marked as volatile. */
extern GTY(()) VEC(tree,gc) *local_variables_to_volatilize;
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
index fef5355c6a6..f136828f60a 100644
--- a/gcc/objc/objc-gnu-runtime-abi-01.c
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -2226,7 +2226,7 @@ static tree
objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
{
tree t;
- t = built_in_decls[BUILT_IN_EH_POINTER];
+ t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
t = build_call_expr (t, 1, integer_zero_node);
return fold_convert (objc_object_type, t);
}
diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
new file mode 100644
index 00000000000..77a98c1d825
--- /dev/null
+++ b/gcc/objc/objc-map.c
@@ -0,0 +1,161 @@
+/* objc-map.c -- Implementation of map data structures for ObjC compiler
+ Copyright 2011 Free Software Foundation, Inc.
+ Written by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program 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 Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "ggc.h"
+#include "objc-map.h"
+
+#define OUT_OF_MEMORY { fprintf (stderr, "Out of memory\n"); abort (); }
+
+static
+size_t
+ATTRIBUTE_PURE
+next_power_of_two (size_t x)
+{
+ size_t result = 1;
+
+ if (x < 2)
+ return 2;
+
+ /* Avoid the long calculation if x is already a power of two. Since
+ we internally always increase/shrink tables by powers of 2, the
+ calculation should only be done once, when the table is first
+ set up. */
+ if ((x & (x - 1)) == 0)
+ return x;
+
+ /* Calculate log_2 by counting how many times we can divide by 2
+ before reaching 0. */
+ while (x > 0)
+ {
+ x = x >> 1;
+ result = result << 1;
+ }
+ return result;
+}
+
+objc_map_t
+objc_map_alloc_ggc (size_t initial_capacity)
+{
+ objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc_stat (1, sizeof (struct objc_map_private));
+ if (map == NULL)
+ OUT_OF_MEMORY;
+
+ initial_capacity = next_power_of_two (initial_capacity);
+
+ map->number_of_slots = initial_capacity;
+ map->mask = initial_capacity - 1;
+ map->maximum_load_factor = 70;
+ map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
+
+ map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree));
+ map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree));
+
+ if (map->slots == NULL)
+ OUT_OF_MEMORY;
+
+ if (map->values == NULL)
+ OUT_OF_MEMORY;
+
+ return map;
+}
+
+void
+objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred)
+{
+ if (map->number_of_non_empty_slots != 0)
+ return;
+
+ map->maximum_load_factor = number_between_zero_and_one_hundred;
+ map->max_number_of_non_empty_slots = (map->number_of_slots * number_between_zero_and_one_hundred) / 100;
+}
+
+int
+objc_map_maximum_load_factor (objc_map_t map)
+{
+ return map->maximum_load_factor;
+}
+
+static void
+objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
+{
+ tree *old_slots = map->slots;
+ tree *old_values = map->values;
+ size_t i, old_number_of_slots = map->number_of_slots;
+
+ if (new_number_of_slots < (map->number_of_non_empty_slots))
+ new_number_of_slots = 2 * map->number_of_non_empty_slots;
+
+ new_number_of_slots = next_power_of_two (new_number_of_slots);
+
+ map->number_of_slots = new_number_of_slots;
+ map->mask = map->number_of_slots - 1;
+ map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
+
+
+ map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree));
+ map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree));
+
+ if (map->slots == NULL)
+ OUT_OF_MEMORY;
+
+ if (map->values == NULL)
+ OUT_OF_MEMORY;
+
+ for (i = 0; i < old_number_of_slots; i++)
+ if (old_slots[i] != OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ size_t k = IDENTIFIER_HASH_VALUE (old_slots[i]) & map->mask;
+
+ if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ map->slots[k] = old_slots[i];
+ map->values[k] = old_values[i];
+ }
+ else
+ {
+ size_t j = 1;
+ while (1)
+ {
+ k = (k + j) & map->mask;
+ if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ map->slots[k] = old_slots[i];
+ map->values[k] = old_values[i];
+ break;
+ }
+ j++;
+ }
+ }
+ }
+
+ ggc_free (old_slots);
+ ggc_free (old_values);
+}
+
+void
+objc_map_private_grow (struct objc_map_private *map)
+{
+ objc_map_private_resize (map, map->number_of_slots * 2);
+}
+
+#include "gt-objc-objc-map.h"
diff --git a/gcc/objc/objc-map.h b/gcc/objc/objc-map.h
new file mode 100644
index 00000000000..c4565de186e
--- /dev/null
+++ b/gcc/objc/objc-map.h
@@ -0,0 +1,309 @@
+/* objc-map.h -- Implementation of map data structures for ObjC compiler
+ Copyright 2011 Free Software Foundation, Inc.
+ Written by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program 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 Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef OBJC_MAP_H
+#define OBJC_MAP_H
+
+/* A map is a data structure that maps a key to a value. In this file
+ we currently have maps that can map a GCC identifier (a tree) to
+ some other GCC tree. This is what the ObjC frontend mostly needs:
+ being able to look up an identifier into an ObjC data structure. A
+ typical usage is mapping ObjC class names (as identifiers) to a
+ tree representing the class.
+
+ This implementation is fast. :-) */
+
+/**
+ ** Private definitions.
+ **/
+
+/* We include private declaration and definitions that are required to
+ provide the implementation of inline functions. You should ignore
+ these definitions (and the implementation of the inline functions)
+ as they are not part of the public API and may change. */
+typedef unsigned int objc_map_private_hash_t;
+
+/* This is used as sentinel. */
+#define OBJC_MAP_PRIVATE_EMPTY_SLOT (tree)0
+
+struct GTY(()) objc_map_private {
+ /* Total number of slots. This is the maximum number of elements
+ that can be currently stored in the map before resizing. This is
+ the number of slots in the C array. Important: this is
+ guaranteed to be a power of 2. When we create (or resize) the
+ map, we round up the size to the next power of 2. This allows us
+ to convert a hash to a position in the hashtable by simply doing
+ "position = hash & mask", where mask is number_of_slots - 1
+ instead of using a modulo (which requires a division). */
+ size_t number_of_slots;
+
+ /* This is number_of_slots - 1, precomputed. */
+ size_t mask;
+
+ /* Number of slots that are not empty (ie, that are active). We
+ keep counts using this variable which can easily be checked
+ against max_number_of_non_empty_slots. */
+ size_t number_of_non_empty_slots;
+
+ /* This is the load factor limit. When the number of non empty
+ slots equals this number, we need to resize the array. This is
+ calculated once, when the slots are resized, and then kept cached
+ so it can be compared quickly when elements are added. */
+ size_t max_number_of_non_empty_slots;
+
+ /* The maximum load factor. */
+ int maximum_load_factor;
+
+ /* These are the keys. */
+ tree * GTY ((length ("%h.number_of_slots"))) slots;
+
+ /* These are the values. values[i] is the the value corresponding
+ to slots[i]. */
+ tree * GTY ((length ("%h.number_of_slots"))) values;
+};
+
+/* Private functions used to resize the map. They may be called by
+ the inline functions when adding elements. */
+extern void
+objc_map_private_grow (struct objc_map_private *map);
+
+
+/**
+ ** The definition of a map.
+ **/
+typedef struct objc_map_private *objc_map_t;
+
+
+/**
+ ** Creating a map.
+ **/
+
+/* objc_map_alloc_ggc() creates a new map which is under GGC. The initial
+ capacity must be specified as an argument; this is used to size the map
+ when it is created. */
+objc_map_t objc_map_alloc_ggc (size_t initial_capacity);
+
+/**
+ ** Performance tuning.
+ **/
+
+/* Set a maximum load factor for the data structure. This is the main
+ tuning parameter to improve performance (at the expense of
+ memory). */
+void objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred);
+
+/* Read the maximum load factor. */
+int objc_map_maximum_load_factor (objc_map_t map);
+
+
+/**
+ ** Getting the value corresponding to a key.
+ **/
+
+/* This is the value returned by objc_map_get() when the value
+ corresponding to a key is not found. */
+#define OBJC_MAP_NOT_FOUND (tree)1
+
+/* objc_map_get() returns the value associated with a certain key,
+ or OBJC_MAP_NOT_FOUND if there is no value associated with that key.
+ Note that you can also use it to simply check if the map contains a
+ pair with a certain key; just compare the result of calling
+ objc_map_get() to OBJC_MAP_NOT_FOUND.
+
+ It is essential to always check the results of the call to make
+ sure it is not OBJC_MAP_NOT_FOUND.
+
+ NULL is a valid value, so a key can be inserted into a map with
+ value NULL, and objc_map_get() will return NULL in that case.
+ So a result of NULL means that they key *was* found, and the value
+ associated with it was NULL. */
+static inline tree
+objc_map_get (objc_map_t map, /* struct tree_identifier * */tree key)
+{
+ /* The inline implementation is private and may change without notice. */
+ objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key);
+ size_t i = hash & map->mask;
+ size_t j = 1;
+
+ if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ return OBJC_MAP_NOT_FOUND;
+
+ if (map->slots[i] == key)
+ return map->values[i];
+
+ while (1)
+ {
+ i = (i + j) & map->mask;
+
+ if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ return OBJC_MAP_NOT_FOUND;
+
+ if (map->slots[i] == key)
+ return map->values[i];
+
+ j++;
+ }
+}
+
+/* objc_map_put() puts a key/value pair into the map. If the map does
+ not contain the key, it is added to it with the specified value.
+ If the map already contains the key, the previous value is replaced
+ with the new one.
+
+ You can use any identifier as key, with the exception of NULL.
+
+ You can use any tree as value, including NULL. */
+static inline
+void objc_map_put (objc_map_t map, /*struct tree_identifier * */tree key, tree value)
+{
+ /* The inline implementation is private and may change without notice. */
+ objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key);
+ size_t i, j = 0;
+
+ if (map->number_of_non_empty_slots == map->max_number_of_non_empty_slots)
+ objc_map_private_grow (map);
+
+ i = hash & map->mask;
+
+ while (1)
+ {
+ if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ map->number_of_non_empty_slots++;
+ map->slots[i] = key;
+ map->values[i] = value;
+ return;
+ }
+ if (map->slots[i] == key)
+ {
+ map->values[i] = value;
+ return;
+ }
+
+ j++;
+ i = (i + j) & map->mask;
+ }
+}
+
+/**
+ ** Iterating over a map using an iterator.
+ **/
+
+/* When using iterators you can iterate directly on the elements in
+ the map, and take an action over each one.
+
+ Here is how you iterate over a hmap_pointer using iterators:
+
+ objc_map_iterator_t i;
+
+ objc_map_iterator_initialize (map, &i);
+
+ while (objc_map_iterator_move_to_next (map, &i))
+ {
+ tree p = objc_map_iterator_current_key (map, i);
+ tree q = objc_map_iterator_current_value (map, i);
+
+ ... do something with p and q ...
+ }
+
+ You'll notice that the functions that modify the iterator (to
+ initialize it, or move it to the next element) take a pointer to it
+ as argument (as in "&i"), while the functions that only read its
+ state (to read the current key/value, or remove the current
+ key/value from the map) take it as a direct argument (as in "i").
+
+ Note that all the objc_map_iterator_*() functions are inline and if
+ you follow the pattern above, the compiler should be able to inline
+ everything into a very efficient loop, roughly equivalent to
+ hand-writing a C loop that iterates directly onto the hmap_pointer
+ internal data structures. */
+
+/* A objc_map_iterator_t variable encapsulates the state of an
+ iteration. The fact that this is actually a size_t (pointing to
+ the index of the slot that we return next) is an internal, private
+ detail of the implementation and may change without notice. */
+typedef size_t objc_map_iterator_t;
+
+/* Initialize an iterator to iterate over the specified objc_map. You
+ must use this before starting the iteration, to get a working
+ iterator. */
+static inline
+void
+objc_map_iterator_initialize (objc_map_t map ATTRIBUTE_UNUSED, objc_map_iterator_t *i)
+{
+ /* The inline implementation is private and may change without notice. */
+ /* This is trivial, but the same API would work to initialize more
+ complicated iterators. */
+ *i = 0;
+}
+
+#define OBJC_MAP_FAILURE 0
+#define OBJC_MAP_SUCCESS 1
+
+/* Move the iterator to the next key/value pair, and return
+ OBJC_MAP_SUCCESS if there is such a key/value pair, and
+ OBJC_MAP_FAILURE if there are no more ones. The iterator must have
+ been initialized using objc_map_iterator_initialize(). Note that
+ because this function is modifying the iterator, you need to pass a
+ pointer to it. */
+static inline
+int
+objc_map_iterator_move_to_next (objc_map_t map, objc_map_iterator_t *i)
+{
+ /* The inline implementation is private and may change without notice. */
+ while (1)
+ {
+ void *slot;
+ if (*i == map->number_of_slots)
+ return OBJC_MAP_FAILURE;
+
+ slot = map->slots[*i];
+ *i = *i + 1;
+ if (slot != OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ return OBJC_MAP_SUCCESS;
+ }
+}
+
+/* Return the current key. You can only call it after you have called
+ objc_map_iterator_move_to_next() at least once (to move to the
+ first element), and only if the last call returned
+ OBJC_MAP_SUCCESS. The behaviour is otherwise undefined, probably a
+ segmentation fault. */
+static inline
+tree
+objc_map_iterator_current_key (objc_map_t map, objc_map_iterator_t i)
+{
+ /* The inline implementation is private and may change without notice. */
+ return map->slots[i - 1];
+}
+
+/* Return the current value. You can only call it after you have
+ called objc_map_iterator_move_to_next() at least once (to move to
+ the first element), and only if the last call returned
+ OBJC_MAP_SUCCESS. The behaviour is otherwise undefined, probably a
+ segmentation fault. */
+static inline
+tree
+objc_map_iterator_current_value (objc_map_t map, objc_map_iterator_t i)
+{
+ /* The inline implementation is private and may change without notice. */
+ return map->values[i - 1];
+}
+
+#endif /* OBJC_MAP_H */
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 6183a21e5e8..c1e60b392d5 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -2919,7 +2919,7 @@ objc_build_exc_ptr (struct objc_try_context **cur_try_context)
else
{
tree t;
- t = built_in_decls[BUILT_IN_EH_POINTER];
+ t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
t = build_call_expr (t, 1, integer_zero_node);
return fold_convert (objc_object_type, t);
}
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 9ef08f01576..4512c846cc0 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -231,6 +231,7 @@ static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
static void finish_catch (struct objc_try_context **, tree);
static tree finish_try_stmt (struct objc_try_context **);
+/* TODO: Use an objc-map. */
static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
bool
@@ -3676,7 +3677,7 @@ static tree
objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
{
tree t;
- t = built_in_decls[BUILT_IN_EH_POINTER];
+ t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
t = build_call_expr (t, 1, integer_zero_node);
return fold_convert (objc_object_type, t);
}
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 51ab2a5016a..bed3b9dcd25 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,10 @@
+2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * Make-lang.in (OBJCXX_OBJS): Added objc-map.o.
+ (objcp/objc-map.o): New rule.
+ (objcp/objcp-act.o): Depend on objc/objc-map.h.
+ * config-lang.in (gtfiles): Added objc-map.h.
+
2011-07-11 Nicola Pero <nicola.pero@meta-innovation.com>
* Make-lang.in (objcp/objc-runtime-shared-support.o): Do not
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index 3dac1735e15..4255bd63909 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -58,6 +58,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objcp-decl.o \
objcp/objc-next-runtime-abi-01.o \
objcp/objc-next-runtime-abi-02.o \
objcp/objc-encoding.o \
+ objcp/objc-map.o \
$(CXX_AND_OBJCXX_OBJS)
obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
@@ -149,6 +150,7 @@ objcp/objcp-act.o : objc/objc-act.c \
$(RTL_H) $(EXPR_H) $(TARGET_H) \
objcp/objcp-decl.h \
objc/objc-encoding.h \
+ objc/objc-map.h \
objc/objc-runtime-hooks.h \
objc/objc-runtime-shared-support.h \
objcp/objcp-decl.h
@@ -165,6 +167,14 @@ objcp/objc-encoding.o : objc/objc-encoding.c \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
$(OUTPUT_OPTION)
+objcp/objc-map.o : objc/objc-map.c \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ objc/objc-map.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+ $(OUTPUT_OPTION)
+
po-generated:
#
diff --git a/gcc/objcp/config-lang.in b/gcc/objcp/config-lang.in
index e80666da5b5..5fd0f06b33b 100644
--- a/gcc/objcp/config-lang.in
+++ b/gcc/objcp/config-lang.in
@@ -46,5 +46,5 @@ subdir_requires="objc cp"
# This list is separated in two parts: the first one is identical to
# the C++ one, the second one contains our ObjC++ additions.
gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \
-\$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
+\$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index fbbef9c785c..05a3493e95f 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2059,7 +2059,7 @@ scan_omp (gimple_seq body, omp_context *ctx)
static tree
build_omp_barrier (void)
{
- return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0);
+ return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
}
/* If a context was created for STMT when it was scanned, return it. */
@@ -2300,7 +2300,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
{
gimple stmt;
- tree tmp;
+ tree tmp, atmp;
ptr = DECL_VALUE_EXPR (new_var);
gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
@@ -2309,8 +2309,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
/* void *tmp = __builtin_alloca */
- stmt
- = gimple_build_call (built_in_decls[BUILT_IN_ALLOCA], 1, x);
+ atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
+ stmt = gimple_build_call (atmp, 1, x);
tmp = create_tmp_var_raw (ptr_type_node, NULL);
gimple_add_tmp_var (tmp);
gimple_call_set_lhs (stmt, tmp);
@@ -2354,8 +2354,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
else
{
- x = build_call_expr_loc (clause_loc,
- built_in_decls[BUILT_IN_ALLOCA], 1, x);
+ tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
+ x = build_call_expr_loc (clause_loc, atmp, 1, x);
}
x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
@@ -2493,7 +2493,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
but it certainly is to C++ operator=. */
if (copyin_seq)
{
- x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+ x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
+ 0);
x = build2 (NE_EXPR, boolean_type_node, x,
build_int_cst (TREE_TYPE (x), 0));
x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
@@ -2688,12 +2689,14 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
}
}
- stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0);
+ stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
+ 0);
gimple_seq_add_stmt (stmt_seqp, stmt);
gimple_seq_add_seq (stmt_seqp, sub_seq);
- stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0);
+ stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
+ 0);
gimple_seq_add_stmt (stmt_seqp, stmt);
}
@@ -2917,7 +2920,8 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
tree t, t1, t2, val, cond, c, clauses;
gimple_stmt_iterator gsi;
gimple stmt;
- int start_ix;
+ enum built_in_function start_ix;
+ int start_ix2;
location_t clause_loc;
VEC(tree,gc) *args;
@@ -2932,10 +2936,11 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
{
case GIMPLE_OMP_FOR:
gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
- start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
- + (region->inner->sched_kind
- == OMP_CLAUSE_SCHEDULE_RUNTIME
- ? 3 : region->inner->sched_kind);
+ start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
+ + (region->inner->sched_kind
+ == OMP_CLAUSE_SCHEDULE_RUNTIME
+ ? 3 : region->inner->sched_kind));
+ start_ix = (enum built_in_function)start_ix2;
break;
case GIMPLE_OMP_SECTIONS:
start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
@@ -3057,7 +3062,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
VEC_splice (tree, args, ws_args);
t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
- built_in_decls[start_ix], args);
+ builtin_decl_explicit (start_ix), args);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
@@ -3073,7 +3078,8 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
false, GSI_CONTINUE_LINKING);
t = build_call_expr_loc (gimple_location (entry_stmt),
- built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0);
+ builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
+ 0);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
}
@@ -3125,7 +3131,8 @@ expand_task_call (basic_block bb, gimple entry_stmt)
else
t3 = build_fold_addr_expr_loc (loc, t);
- t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3,
+ t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
+ 7, t1, t2, t3,
gimple_omp_task_arg_size (entry_stmt),
gimple_omp_task_arg_align (entry_stmt), cond, flags);
@@ -3150,7 +3157,7 @@ maybe_catch_exception (gimple_seq body)
if (lang_hooks.eh_protect_cleanup_actions != NULL)
decl = lang_hooks.eh_protect_cleanup_actions ();
else
- decl = built_in_decls[BUILT_IN_TRAP];
+ decl = builtin_decl_explicit (BUILT_IN_TRAP);
g = gimple_build_eh_must_not_throw (decl);
g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
@@ -3297,10 +3304,10 @@ optimize_omp_library_calls (gimple entry_stmt)
{
basic_block bb;
gimple_stmt_iterator gsi;
- tree thr_num_id
- = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]);
- tree num_thr_id
- = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]);
+ tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
+ tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
+ tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
+ tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
&& find_omp_clause (gimple_omp_task_clauses (entry_stmt),
OMP_CLAUSE_UNTIED) != NULL);
@@ -3325,10 +3332,10 @@ optimize_omp_library_calls (gimple entry_stmt)
during the execution of the task region. */
if (untied_task)
continue;
- built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM];
+ built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
}
else if (DECL_NAME (decl) == num_thr_id)
- built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS];
+ built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
else
continue;
@@ -3812,7 +3819,7 @@ expand_omp_for_generic (struct omp_region *region,
{
/* In a combined parallel loop, emit a call to
GOMP_loop_foo_next. */
- t = build_call_expr (built_in_decls[next_fn], 2,
+ t = build_call_expr (builtin_decl_explicit (next_fn), 2,
build_fold_addr_expr (istart0),
build_fold_addr_expr (iend0));
}
@@ -3848,34 +3855,36 @@ expand_omp_for_generic (struct omp_region *region,
if (fd->chunk_size)
{
t = fold_convert (fd->iter_type, fd->chunk_size);
- t = build_call_expr (built_in_decls[start_fn], 6,
- t0, t1, t2, t, t3, t4);
+ t = build_call_expr (builtin_decl_explicit (start_fn),
+ 6, t0, t1, t2, t, t3, t4);
}
else
- t = build_call_expr (built_in_decls[start_fn], 5,
- t0, t1, t2, t3, t4);
+ t = build_call_expr (builtin_decl_explicit (start_fn),
+ 5, t0, t1, t2, t3, t4);
}
else
{
tree t5;
tree c_bool_type;
+ tree bfn_decl;
/* The GOMP_loop_ull_*start functions have additional boolean
argument, true for < loops and false for > loops.
In Fortran, the C bool type can be different from
boolean_type_node. */
- c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls[start_fn]));
+ bfn_decl = builtin_decl_explicit (start_fn);
+ c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
t5 = build_int_cst (c_bool_type,
fd->loop.cond_code == LT_EXPR ? 1 : 0);
if (fd->chunk_size)
{
+ tree bfn_decl = builtin_decl_explicit (start_fn);
t = fold_convert (fd->iter_type, fd->chunk_size);
- t = build_call_expr (built_in_decls[start_fn], 7,
- t5, t0, t1, t2, t, t3, t4);
+ t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
}
else
- t = build_call_expr (built_in_decls[start_fn], 6,
- t5, t0, t1, t2, t3, t4);
+ t = build_call_expr (builtin_decl_explicit (start_fn),
+ 6, t5, t0, t1, t2, t3, t4);
}
}
if (TREE_TYPE (t) != boolean_type_node)
@@ -4031,7 +4040,7 @@ expand_omp_for_generic (struct omp_region *region,
/* Emit code to get the next parallel iteration in L2_BB. */
gsi = gsi_start_bb (l2_bb);
- t = build_call_expr (built_in_decls[next_fn], 2,
+ t = build_call_expr (builtin_decl_explicit (next_fn), 2,
build_fold_addr_expr (istart0),
build_fold_addr_expr (iend0));
t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
@@ -4046,9 +4055,9 @@ expand_omp_for_generic (struct omp_region *region,
/* Add the loop cleanup function. */
gsi = gsi_last_bb (exit_bb);
if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
- t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
+ t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
else
- t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
+ t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
stmt = gimple_build_call (t, 0);
gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
gsi_remove (&gsi, true);
@@ -4169,12 +4178,12 @@ expand_omp_for_static_nochunk (struct omp_region *region,
gsi = gsi_last_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
- t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+ t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
t = fold_convert (itype, t);
nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+ t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
t = fold_convert (itype, t);
threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
@@ -4391,12 +4400,12 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
si = gsi_last_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
- t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0);
+ t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
t = fold_convert (itype, t);
nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+ t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
t = fold_convert (itype, t);
threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
true, GSI_SAME_STMT);
@@ -4658,14 +4667,14 @@ expand_omp_for (struct omp_region *region)
fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
? 3 : fd.sched_kind;
fn_index += fd.have_ordered * 4;
- start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
- next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
+ start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
+ next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
if (fd.iter_type == long_long_unsigned_type_node)
{
- start_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_START
- - BUILT_IN_GOMP_LOOP_STATIC_START;
- next_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
- - BUILT_IN_GOMP_LOOP_STATIC_NEXT;
+ start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
+ - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
+ next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
+ - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
}
expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
(enum built_in_function) next_ix);
@@ -4778,13 +4787,13 @@ expand_omp_sections (struct omp_region *region)
call GOMP_sections_start. */
t = build_int_cst (unsigned_type_node,
exit_reachable ? len - 1 : len);
- u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
+ u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
stmt = gimple_build_call (u, 1, t);
}
else
{
/* Otherwise, call GOMP_sections_next. */
- u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
+ u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
stmt = gimple_build_call (u, 0);
}
gimple_call_set_lhs (stmt, vin);
@@ -4866,16 +4875,19 @@ expand_omp_sections (struct omp_region *region)
VEC_free (tree, heap, label_vec);
si = gsi_start_bb (default_bb);
- stmt = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0);
+ stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
if (exit_reachable)
{
+ tree bfn_decl;
+
/* Code to get the next section goes in L1_BB. */
si = gsi_last_bb (l1_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
- stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0);
+ bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
+ stmt = gimple_build_call (bfn_decl, 0);
gimple_call_set_lhs (stmt, vnext);
gsi_insert_after (&si, stmt, GSI_SAME_STMT);
gsi_remove (&si, true);
@@ -4885,9 +4897,9 @@ expand_omp_sections (struct omp_region *region)
/* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
si = gsi_last_bb (l2_bb);
if (gimple_omp_return_nowait_p (gsi_stmt (si)))
- t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
+ t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
else
- t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
+ t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
stmt = gimple_build_call (t, 0);
gsi_insert_after (&si, stmt, GSI_SAME_STMT);
gsi_remove (&si, true);
@@ -4995,7 +5007,7 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
tree addr, tree loaded_val,
tree stored_val, int index)
{
- enum built_in_function oldbase, newbase;
+ enum built_in_function oldbase, newbase, tmpbase;
tree decl, itype, call;
direct_optab optab, oldoptab, newoptab;
tree lhs, rhs;
@@ -5085,7 +5097,9 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
else
return false;
- decl = built_in_decls[(need_new ? newbase : oldbase) + index + 1];
+ tmpbase = ((enum built_in_function)
+ ((need_new ? newbase : oldbase) + index + 1));
+ decl = builtin_decl_explicit (tmpbase);
if (decl == NULL_TREE)
return false;
itype = TREE_TYPE (TREE_TYPE (decl));
@@ -5166,8 +5180,11 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
basic_block loop_header = single_succ (load_bb);
gimple phi, stmt;
edge e;
+ enum built_in_function fncode;
- cmpxchg = built_in_decls[BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N + index + 1];
+ fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
+ + index + 1);
+ cmpxchg = builtin_decl_explicit (fncode);
if (cmpxchg == NULL_TREE)
return false;
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
@@ -5355,7 +5372,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
si = gsi_last_bb (load_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
- t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
+ t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
t = build_call_expr (t, 0);
force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
@@ -5370,7 +5387,7 @@ expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
stored_val);
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
- t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
+ t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
t = build_call_expr (t, 0);
force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
gsi_remove (&si, true);
@@ -5806,7 +5823,7 @@ lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
gimple call, cond;
tree lhs, decl;
- decl = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
+ decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
call = gimple_build_call (decl, 0);
gimple_call_set_lhs (call, lhs);
@@ -5855,7 +5872,7 @@ lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
static void
lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
{
- tree ptr_type, t, l0, l1, l2;
+ tree ptr_type, t, l0, l1, l2, bfn_decl;
gimple_seq copyin_seq;
location_t loc = gimple_location (single_stmt);
@@ -5868,7 +5885,8 @@ lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
l1 = create_artificial_label (loc);
l2 = create_artificial_label (loc);
- t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0);
+ bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
+ t = build_call_expr_loc (loc, bfn_decl, 0);
t = fold_convert_loc (loc, ptr_type, t);
gimplify_assign (ctx->receiver_decl, t, pre_p);
@@ -5887,8 +5905,8 @@ lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
&copyin_seq, ctx);
t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
- t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END],
- 1, t);
+ bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
+ t = build_call_expr_loc (loc, bfn_decl, 1, t);
gimplify_and_add (t, pre_p);
t = build_and_jump (&l2);
@@ -5955,7 +5973,7 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
static void
lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
- tree block, lab = NULL, x;
+ tree block, lab = NULL, x, bfn_decl;
gimple stmt = gsi_stmt (*gsi_p), bind;
location_t loc = gimple_location (stmt);
gimple_seq tseq;
@@ -5967,7 +5985,8 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
block);
- x = build_call_expr_loc (loc, built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0);
+ bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
+ x = build_call_expr_loc (loc, bfn_decl, 0);
x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
tseq = NULL;
@@ -6006,7 +6025,8 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt),
block);
- x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
+ x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
+ 0);
gimple_bind_add_stmt (bind, x);
lower_omp (gimple_omp_body (stmt), ctx);
@@ -6014,7 +6034,7 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_bind_add_seq (bind, gimple_omp_body (stmt));
gimple_omp_set_body (stmt, NULL);
- x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
+ x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
gimple_bind_add_stmt (bind, x);
gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
@@ -6080,19 +6100,19 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
else
decl = (tree) n->value;
- lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
+ lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
- unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
+ unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
unlock = build_call_expr_loc (loc, unlock, 1,
build_fold_addr_expr_loc (loc, decl));
}
else
{
- lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
+ lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
lock = build_call_expr_loc (loc, lock, 0);
- unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
+ unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
unlock = build_call_expr_loc (loc, unlock, 0);
}
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 5cdcd95f12a..558c0fa107f 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -479,6 +479,14 @@ optab_for_tree_code (enum tree_code code, const_tree type,
return TYPE_UNSIGNED (type) ?
vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ return TYPE_UNSIGNED (type) ?
+ vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;
+
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ return TYPE_UNSIGNED (type) ?
+ vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab;
+
case VEC_UNPACK_HI_EXPR:
return TYPE_UNSIGNED (type) ?
vec_unpacku_hi_optab : vec_unpacks_hi_optab;
@@ -735,6 +743,41 @@ expand_vec_shift_expr (sepops ops, rtx target)
return eops[0].value;
}
+/* Create a new vector value in VMODE with all elements set to OP. The
+ mode of OP must be the element mode of VMODE. If OP is a constant,
+ then the return value will be a constant. */
+
+static rtx
+expand_vector_broadcast (enum machine_mode vmode, rtx op)
+{
+ enum insn_code icode;
+ rtvec vec;
+ rtx ret;
+ int i, n;
+
+ gcc_checking_assert (VECTOR_MODE_P (vmode));
+
+ n = GET_MODE_NUNITS (vmode);
+ vec = rtvec_alloc (n);
+ for (i = 0; i < n; ++i)
+ RTVEC_ELT (vec, i) = op;
+
+ if (CONSTANT_P (op))
+ return gen_rtx_CONST_VECTOR (vmode, vec);
+
+ /* ??? If the target doesn't have a vec_init, then we have no easy way
+ of performing this operation. Most of this sort of generic support
+ is hidden away in the vector lowering support in gimple. */
+ icode = optab_handler (vec_init_optab, vmode);
+ if (icode == CODE_FOR_nothing)
+ return NULL;
+
+ ret = gen_reg_rtx (vmode);
+ emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
+
+ return ret;
+}
+
/* This subroutine of expand_doubleword_shift handles the cases in which
the effective shift value is >= BITS_PER_WORD. The arguments and return
value are the same as for the parent routine, except that SUPERWORD_OP1
@@ -1533,6 +1576,36 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
}
}
+ /* If this is a vector shift by a scalar, see if we can do a vector
+ shift by a vector. If so, broadcast the scalar into a vector. */
+ if (mclass == MODE_VECTOR_INT)
+ {
+ optab otheroptab = NULL;
+
+ if (binoptab == ashl_optab)
+ otheroptab = vashl_optab;
+ else if (binoptab == ashr_optab)
+ otheroptab = vashr_optab;
+ else if (binoptab == lshr_optab)
+ otheroptab = vlshr_optab;
+ else if (binoptab == rotl_optab)
+ otheroptab = vrotl_optab;
+ else if (binoptab == rotr_optab)
+ otheroptab = vrotr_optab;
+
+ if (otheroptab && optab_handler (otheroptab, mode) != CODE_FOR_nothing)
+ {
+ rtx vop1 = expand_vector_broadcast (mode, op1);
+ if (vop1)
+ {
+ temp = expand_binop_directly (mode, otheroptab, op0, vop1,
+ target, unsignedp, methods, last);
+ if (temp)
+ return temp;
+ }
+ }
+ }
+
/* Look for a wider mode of the same class for which we think we
can open-code the operation. Check for a widening multiply at the
wider mode as well. */
@@ -6132,6 +6205,10 @@ init_optabs (void)
init_optab (vec_widen_umult_lo_optab, UNKNOWN);
init_optab (vec_widen_smult_hi_optab, UNKNOWN);
init_optab (vec_widen_smult_lo_optab, UNKNOWN);
+ init_optab (vec_widen_ushiftl_hi_optab, UNKNOWN);
+ init_optab (vec_widen_ushiftl_lo_optab, UNKNOWN);
+ init_optab (vec_widen_sshiftl_hi_optab, UNKNOWN);
+ init_optab (vec_widen_sshiftl_lo_optab, UNKNOWN);
init_optab (vec_unpacks_hi_optab, UNKNOWN);
init_optab (vec_unpacks_lo_optab, UNKNOWN);
init_optab (vec_unpacku_hi_optab, UNKNOWN);
@@ -6620,6 +6697,208 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
}
+/* Return true if VEC_PERM_EXPR can be expanded using SIMD extensions
+ of the CPU. SEL may be NULL, which stands for an unknown constant. */
+
+bool
+can_vec_perm_expr_p (tree type, tree sel)
+{
+ enum machine_mode mode, qimode;
+ mode = TYPE_MODE (type);
+
+ /* If the target doesn't implement a vector mode for the vector type,
+ then no operations are supported. */
+ if (!VECTOR_MODE_P (mode))
+ return false;
+
+ if (sel == NULL || TREE_CODE (sel) == VECTOR_CST)
+ {
+ if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
+ && (sel == NULL || targetm.vectorize.builtin_vec_perm_ok (type, sel)))
+ return true;
+ }
+
+ if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
+ return true;
+
+ /* We allow fallback to a QI vector mode, and adjust the mask. */
+ qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
+ if (!VECTOR_MODE_P (qimode))
+ return false;
+
+ /* ??? For completeness, we ought to check the QImode version of
+ vec_perm_const_optab. But all users of this implicit lowering
+ feature implement the variable vec_perm_optab. */
+ if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
+ return false;
+
+ /* In order to support the lowering of non-constant permutations,
+ we need to support shifts and adds. */
+ if (sel != NULL && TREE_CODE (sel) != VECTOR_CST)
+ {
+ if (GET_MODE_UNIT_SIZE (mode) > 2
+ && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
+ && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
+ return false;
+ if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
+ return false;
+ }
+
+ return true;
+}
+
+/* A subroutine of expand_vec_perm_expr for expanding one vec_perm insn. */
+
+static rtx
+expand_vec_perm_expr_1 (enum insn_code icode, rtx target,
+ rtx v0, rtx v1, rtx sel)
+{
+ enum machine_mode tmode = GET_MODE (target);
+ enum machine_mode smode = GET_MODE (sel);
+ struct expand_operand ops[4];
+
+ create_output_operand (&ops[0], target, tmode);
+ create_input_operand (&ops[3], sel, smode);
+
+ /* Make an effort to preserve v0 == v1. The target expander is able to
+ rely on this to determine if we're permuting a single input operand. */
+ if (rtx_equal_p (v0, v1))
+ {
+ if (!insn_operand_matches (icode, 1, v0))
+ v0 = force_reg (tmode, v0);
+ gcc_checking_assert (insn_operand_matches (icode, 1, v0));
+ gcc_checking_assert (insn_operand_matches (icode, 2, v0));
+
+ create_fixed_operand (&ops[1], v0);
+ create_fixed_operand (&ops[2], v0);
+ }
+ else
+ {
+ create_input_operand (&ops[1], v0, tmode);
+ create_input_operand (&ops[2], v1, tmode);
+ }
+
+ if (maybe_expand_insn (icode, 4, ops))
+ return ops[0].value;
+ return NULL_RTX;
+}
+
+/* Generate instructions for VEC_PERM_EXPR given its type and three
+ operands. */
+rtx
+expand_vec_perm_expr (tree type, tree v0, tree v1, tree sel, rtx target)
+{
+ enum insn_code icode;
+ enum machine_mode mode = TYPE_MODE (type);
+ enum machine_mode qimode;
+ rtx v0_rtx, v1_rtx, sel_rtx, *vec, vt, tmp;
+ unsigned int i, w, e, u;
+
+ if (!target)
+ target = gen_reg_rtx (mode);
+ v0_rtx = expand_normal (v0);
+ if (operand_equal_p (v0, v1, 0))
+ v1_rtx = v0_rtx;
+ else
+ v1_rtx = expand_normal (v1);
+ sel_rtx = expand_normal (sel);
+
+ /* If the input is a constant, expand it specially. */
+ if (CONSTANT_P (sel_rtx))
+ {
+ icode = direct_optab_handler (vec_perm_const_optab, mode);
+ if (icode != CODE_FOR_nothing
+ && targetm.vectorize.builtin_vec_perm_ok (TREE_TYPE (v0), sel)
+ && (tmp = expand_vec_perm_expr_1 (icode, target, v0_rtx,
+ v1_rtx, sel_rtx)) != NULL)
+ return tmp;
+ }
+
+ /* Otherwise fall back to a fully variable permuation. */
+ icode = direct_optab_handler (vec_perm_optab, mode);
+ if (icode != CODE_FOR_nothing
+ && (tmp = expand_vec_perm_expr_1 (icode, target, v0_rtx,
+ v1_rtx, sel_rtx)) != NULL)
+ return tmp;
+
+ /* As a special case to aid several targets, lower the element-based
+ permutation to a byte-based permutation and try again. */
+ qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
+ if (!VECTOR_MODE_P (qimode))
+ return NULL_RTX;
+
+ /* ??? For completeness, we ought to check the QImode version of
+ vec_perm_const_optab. But all users of this implicit lowering
+ feature implement the variable vec_perm_optab. */
+ icode = direct_optab_handler (vec_perm_optab, qimode);
+ if (icode == CODE_FOR_nothing)
+ return NULL_RTX;
+
+ w = GET_MODE_SIZE (mode);
+ e = GET_MODE_NUNITS (mode);
+ u = GET_MODE_UNIT_SIZE (mode);
+ vec = XALLOCAVEC (rtx, w);
+
+ if (CONSTANT_P (sel_rtx))
+ {
+ unsigned int j;
+ for (i = 0; i < e; ++i)
+ {
+ unsigned int this_e = INTVAL (XVECEXP (sel_rtx, 0, i));
+ this_e &= 2 * e - 1;
+ this_e *= u;
+
+ for (j = 0; j < u; ++j)
+ vec[i * u + j] = GEN_INT (this_e + j);
+ }
+ sel_rtx = gen_rtx_CONST_VECTOR (qimode, gen_rtvec_v (w, vec));
+ }
+ else
+ {
+ /* Multiply each element by its byte size. */
+ if (u == 2)
+ sel_rtx = expand_simple_binop (mode, PLUS, sel_rtx, sel_rtx,
+ sel_rtx, 0, OPTAB_DIRECT);
+ else
+ sel_rtx = expand_simple_binop (mode, ASHIFT, sel_rtx,
+ GEN_INT (exact_log2 (u)),
+ sel_rtx, 0, OPTAB_DIRECT);
+ gcc_assert (sel_rtx);
+
+ /* Broadcast the low byte each element into each of its bytes. */
+ for (i = 0; i < w; ++i)
+ {
+ int this_e = i / u * u;
+ if (BYTES_BIG_ENDIAN)
+ this_e += u - 1;
+ vec[i] = GEN_INT (this_e);
+ }
+ vt = gen_rtx_CONST_VECTOR (qimode, gen_rtvec_v (w, vec));
+ sel_rtx = gen_lowpart (qimode, sel_rtx);
+ sel_rtx = expand_vec_perm_expr_1 (icode, gen_reg_rtx (qimode),
+ sel_rtx, sel_rtx, vt);
+ gcc_assert (sel_rtx != NULL);
+
+ /* Add the byte offset to each byte element. */
+ /* Note that the definition of the indicies here is memory ordering,
+ so there should be no difference between big and little endian. */
+ for (i = 0; i < w; ++i)
+ vec[i] = GEN_INT (i % u);
+ vt = gen_rtx_CONST_VECTOR (qimode, gen_rtvec_v (w, vec));
+ sel_rtx = expand_simple_binop (qimode, PLUS, sel_rtx, vt,
+ NULL_RTX, 0, OPTAB_DIRECT);
+ gcc_assert (sel_rtx);
+ }
+
+ tmp = expand_vec_perm_expr_1 (icode, gen_lowpart (qimode, target),
+ gen_lowpart (qimode, v0_rtx),
+ gen_lowpart (qimode, v1_rtx), sel_rtx);
+ gcc_assert (tmp != NULL);
+
+ return gen_lowpart (mode, tmp);
+}
+
+
/* Return insn code for a conditional operator with a comparison in
mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 56df6718462..86e0ec93bc1 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -351,6 +351,12 @@ enum optab_index
OTI_vec_widen_umult_lo,
OTI_vec_widen_smult_hi,
OTI_vec_widen_smult_lo,
+ /* Widening shift left.
+ The high/low part of the resulting vector is returned. */
+ OTI_vec_widen_ushiftl_hi,
+ OTI_vec_widen_ushiftl_lo,
+ OTI_vec_widen_sshiftl_hi,
+ OTI_vec_widen_sshiftl_lo,
/* Extract and widen the high/low part of a vector of signed or
floating point elements. */
OTI_vec_unpacks_hi,
@@ -544,6 +550,10 @@ enum optab_index
#define vec_widen_umult_lo_optab (&optab_table[OTI_vec_widen_umult_lo])
#define vec_widen_smult_hi_optab (&optab_table[OTI_vec_widen_smult_hi])
#define vec_widen_smult_lo_optab (&optab_table[OTI_vec_widen_smult_lo])
+#define vec_widen_ushiftl_hi_optab (&optab_table[OTI_vec_widen_ushiftl_hi])
+#define vec_widen_ushiftl_lo_optab (&optab_table[OTI_vec_widen_ushiftl_lo])
+#define vec_widen_sshiftl_hi_optab (&optab_table[OTI_vec_widen_sshiftl_hi])
+#define vec_widen_sshiftl_lo_optab (&optab_table[OTI_vec_widen_sshiftl_lo])
#define vec_unpacks_hi_optab (&optab_table[OTI_vec_unpacks_hi])
#define vec_unpacks_lo_optab (&optab_table[OTI_vec_unpacks_lo])
#define vec_unpacku_hi_optab (&optab_table[OTI_vec_unpacku_hi])
@@ -685,6 +695,10 @@ enum direct_optab_index
/* Atomic clear with release semantics. */
DOI_sync_lock_release,
+ /* Vector permutation. */
+ DOI_vec_perm,
+ DOI_vec_perm_const,
+
DOI_MAX
};
@@ -730,6 +744,8 @@ typedef struct direct_optab_d *direct_optab;
(&direct_optab_table[(int) DOI_sync_lock_test_and_set])
#define sync_lock_release_optab \
(&direct_optab_table[(int) DOI_sync_lock_release])
+#define vec_perm_optab (&direct_optab_table[DOI_vec_perm])
+#define vec_perm_const_optab (&direct_optab_table[(int) DOI_vec_perm_const])
/* Target-dependent globals. */
struct target_optabs {
@@ -884,6 +900,12 @@ extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
/* Generate code for VEC_LSHIFT_EXPR and VEC_RSHIFT_EXPR. */
extern rtx expand_vec_shift_expr (sepops, rtx);
+/* Return tree if target supports vector operations for VEC_PERM_EXPR. */
+extern bool can_vec_perm_expr_p (tree, tree);
+
+/* Generate code for VEC_PERM_EXPR. */
+extern rtx expand_vec_perm_expr (tree, tree, tree, tree, rtx);
+
/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
if the target does not have such an insn. */
diff --git a/gcc/opts.c b/gcc/opts.c
index c16ca09b81f..20cc6187366 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -434,6 +434,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_1_PLUS, OPT_fipa_reference, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fipa_profile, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fmerge_constants, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 },
{ OPT_LEVELS_1_PLUS, OPT_ftree_bit_ccp, NULL, 1 },
diff --git a/gcc/passes.c b/gcc/passes.c
index 4d8ca6e42f2..887007f6dde 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1355,7 +1355,6 @@ init_optimization_passes (void)
NEXT_PASS (pass_vectorize);
{
struct opt_pass **p = &pass_vectorize.pass.sub;
- NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_dce_loop);
}
NEXT_PASS (pass_predcom);
@@ -1367,6 +1366,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_lim);
NEXT_PASS (pass_tree_loop_done);
}
+ NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_cse_reciprocals);
NEXT_PASS (pass_reassoc);
NEXT_PASS (pass_vrp);
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 3906bffc68b..63d1cae4ede 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -1,5 +1,5 @@
/* Support for GCC plugin mechanism.
- Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -149,7 +149,7 @@ add_new_plugin (const char* plugin_name)
plugin_name, ".so", NULL);
if (access (plugin_name, R_OK))
fatal_error
- ("inacessible plugin file %s expanded from short plugin name %s: %m",
+ ("inaccessible plugin file %s expanded from short plugin name %s: %m",
plugin_name, base_name);
}
else
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index c4ba7cf2f54..6cf5a4801ca 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,7 @@
+2011-10-03 Joseph Myers <joseph@codesourcery.com>
+
+ * de.po: Update.
+
2011-09-02 Joseph Myers <joseph@codesourcery.com>
* ja.po: Update.
diff --git a/gcc/po/de.po b/gcc/po/de.po
index 147a4e9578f..cad983aa2c3 100644
--- a/gcc/po/de.po
+++ b/gcc/po/de.po
@@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: gcc 4.6.1\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
"POT-Creation-Date: 2011-06-21 10:27+0000\n"
-"PO-Revision-Date: 2011-07-31 14:14+0200\n"
+"PO-Revision-Date: 2011-10-03 14:14+0200\n"
"Last-Translator: Roland Stigge <stigge@antcom.de>\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
"Language: de\n"
@@ -33219,9 +33219,9 @@ msgid "'a1' argument of '%s' intrinsic at %L must be INTEGER, REAL or CHARACTER"
msgstr "Argument »a1« des intrinsischen »%s« bei %L muss INTEGER, REAL oder CHARACTER sein"
#: fortran/check.c:2282
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Argument types of '%s' intrinsic at %L must match (%s/%s)"
-msgstr "Argument »a%d« des intrinsischen »%s« bei %L muss %s(%d) sein"
+msgstr "Argumenttypen des intrinsischen »%s« bei %L müssen passen (%s/%s)"
#: fortran/check.c:2296
#, gcc-internal-format, gfc-internal-format
@@ -33239,9 +33239,9 @@ msgid "'%s' argument of '%s' intrinsic at %L must be of rank 1 or 2"
msgstr "Argument »%s« des intrinsischen »%s« bei %L muss vom Rang 1 oder 2 sein"
#: fortran/check.c:2499
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L must be INTEGER"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss ein POINTER sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L muss ein INTEGER sein"
#: fortran/check.c:2568
#, gcc-internal-format, gfc-internal-format
@@ -33254,9 +33254,9 @@ msgid "the '%s' and '%s' arguments of '%s' intrinsic at %L must be of the same k
msgstr "Argumente »%s« und »%s« des intrinsischen »%s« bei %L müssen von der selben Art %d/%d sein"
#: fortran/check.c:2718 fortran/check.c:3850
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L must provide at least as many elements as there are .TRUE. values in '%s' (%ld/%d)"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss vom gleichen Typ und gleicher Art wie »%s« sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L muss mindestens so viele Elemente haben wie es .TRUE.-Werte »%s« (%ld/%d) gibt"
#: fortran/check.c:2776
#, gcc-internal-format, gfc-internal-format
@@ -33279,9 +33279,9 @@ msgid "'shape' argument of 'reshape' intrinsic at %L must be an array of constan
msgstr "Argument »shape« des intrinsischen »reshape« bei %L muss ein Feld konstanter Größe sein"
#: fortran/check.c:2936
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L is empty"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss %s sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L ist leer"
#: fortran/check.c:2943
#, gcc-internal-format, gfc-internal-format
@@ -33289,24 +33289,24 @@ msgid "'shape' argument of 'reshape' intrinsic at %L has more than %d elements"
msgstr "Argument »shape« des intrinsischen »reshape« bei %L hat mehr als %d Elemente"
#: fortran/check.c:2960
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L has negative element (%d)"
-msgstr "Argument »a%d« des intrinsischen »%s« bei %L muss %s(%d) sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L hat negatives Element (%d)"
#: fortran/check.c:3000
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L has wrong number of elements (%d/%d)"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss vom Rang %d sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L hat falsche Anzahl der Elemente (%d/%d)"
#: fortran/check.c:3018
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L has out-of-range dimension (%d)"
-msgstr "Argument »dim« des intrinsischen »%s« bei %L ist kein gültiger Dimensionsindex"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L hat Dimension außerhalb des Wertebereiches (%d)"
#: fortran/check.c:3027
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L has invalid permutation of dimensions (dimension '%d' duplicated)"
-msgstr "Argument »dim« des intrinsischen »%s« bei %L ist kein gültiger Dimensionsindex"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L hat ungültige Permutation der Dimensionen (Dimension »%d« doppelt)"
#: fortran/check.c:3063
#, gcc-internal-format, gfc-internal-format
@@ -33314,24 +33314,24 @@ msgid "Without padding, there are not enough elements in the intrinsic RESHAPE s
msgstr "Ohne Auffüllen gibt es nicht genügend Elemente in eingebauter RESHAPE-Quelle bei %L um zur Form zu passen"
#: fortran/check.c:3081 fortran/check.c:3099
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L must be of a derived type"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L darf kein abgeleiteter Typ sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L muss abgeleiteten Typ haben"
#: fortran/check.c:3090 fortran/check.c:3108
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L must be of an extensible type"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss ein numerischer Typ sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L muss erweiterbaren Typ haben"
#: fortran/check.c:3207
#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: SELECTED_REAL_KIND with neither 'P' nor 'R' argument at %L"
-msgstr ""
+msgstr "Fortran 2008: SELECTED_REAL_KIND ohne Argument »P« oder »R« bei %L"
#: fortran/check.c:3238
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: '%s' intrinsic with RADIX argument at %L"
-msgstr "Fortran 2003: intrinsisches »%s« mit KIND-Argument bei %L"
+msgstr "Fortran 2008: intrinsisches »%s« mit RADIX-Argument bei %L"
#: fortran/check.c:3273
#, gcc-internal-format, gfc-internal-format
@@ -33339,14 +33339,14 @@ msgid "'source' argument of 'shape' intrinsic at %L must not be an assumed size
msgstr "Argument »source« des intrinsischen »shape« bei %L darf kein Feld impliziter Größe sein"
#: fortran/check.c:3357
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L must be be an interoperable data entity"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss ein Feld sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L muss kompatible Datenentität sein"
#: fortran/check.c:3386
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "GNU extension: non double precision REAL argument to %s intrinsic at %L"
-msgstr "Fehlende Argumente für intrinsisches %s bei %L"
+msgstr "GNU-Erweiterung: REAL-Argument ohne doppelte Genauigkeit für intrinsisches %s bei %L"
#: fortran/check.c:3399
#, gcc-internal-format, gfc-internal-format
@@ -33354,19 +33354,19 @@ msgid "'%s' argument of '%s' intrinsic at %L must be less than rank %d"
msgstr "Argument »%s« für intrinsisches »%s« bei %L muss geringer als Rang %d sein"
#: fortran/check.c:3418
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L is not a valid dimension index"
-msgstr "Argument »dim« des intrinsischen »%s« bei %L ist kein gültiger Dimensionsindex"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L ist kein gültiger Dimensionsindex"
#: fortran/check.c:3679
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "%s argument to IMAGE_INDEX must be a rank one array at %L"
-msgstr "Effektives Argument für »%s« muss ein Zeiger bei %L sein"
+msgstr "Argument »%s« für IMAGE_INDEX muss Feld mit Rang 1 bei %L sein"
#: fortran/check.c:3699
#, gcc-internal-format, gfc-internal-format
msgid "DIM argument without ARRAY argument not allowed for THIS_IMAGE intrinsic at %L"
-msgstr ""
+msgstr "DIM-Argument ohne ARRAY-Argument ist für intrinsisches THIS_IMAGE bei %L nicht erlaubt"
#: fortran/check.c:3729
#, gcc-internal-format, gfc-internal-format
@@ -33374,19 +33374,19 @@ msgid "'MOLD' argument of 'TRANSFER' intrinsic at %L must not be %s"
msgstr "Argument »MOLD« des intrinsischen »TRANSFER« bei %L darf nicht %s sein"
#: fortran/check.c:3864
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' argument of '%s' intrinsic at %L must have the same rank as '%s' or be a scalar"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss von der selben Art wie »%s« sein"
+msgstr "Argument »%s« des intrinsischen »%s« bei %L muss den selben Rang wie »%s« haben oder skalar sein"
#: fortran/check.c:3877
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' and '%s' arguments of '%s' intrinsic at %L must have identical shape."
-msgstr "Argumente »%s« und »%s« des intrinsischen »%s« bei %L müssen den selben Typ haben"
+msgstr "Argumente »%s« und »%s« des intrinsischen »%s« bei %L müssen gleiche Form haben."
#: fortran/check.c:4136 fortran/check.c:4168
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Size of '%s' argument of '%s' intrinsic at %L too small (%i/%i)"
-msgstr "Argument »%s« des intrinsischen »%s« bei %L muss %s sein"
+msgstr "Größe des Arguments »%s« des intrinsischen »%s« bei %L ist zu klein (%i/%i)"
#: fortran/check.c:4176
#, gcc-internal-format, gfc-internal-format
@@ -33404,31 +33404,31 @@ msgid "'%s' argument of '%s' intrinsic at %L must be INTEGER or LOGICAL"
msgstr "Argument »%s« für intrinsisches »%s« bei %L muss INTEGER oder LOGICAL sein"
#: fortran/class.c:199
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Polymorphic array at %C not yet supported"
-msgstr "Parameter verschiedener Typen in Zeigerzuweisung bei %L"
+msgstr "Polymorphes Feld bei %C wird noch nicht unterstützt"
#. Since the extension field is 8 bit wide, we can only have
#. up to 255 extension levels.
#: fortran/class.c:270 fortran/decl.c:7344
#, gcc-internal-format, gfc-internal-format
msgid "Maximum extension level reached with type '%s' at %L"
-msgstr ""
+msgstr "Höchste Erweiterungsstufe mit Typ »%s« bei %L erreicht"
#: fortran/class.c:650 fortran/class.c:724
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' of '%s' is PRIVATE at %L"
-msgstr "Ergebnis von %s ist NaN bei %L"
+msgstr "»%s« von »%s« ist bei %L PRIVATE"
#: fortran/cpp.c:443
#, gcc-internal-format
msgid "To enable preprocessing, use -cpp"
-msgstr ""
+msgstr "Zum Einschalten der Vorverarbeitung -cpp verwenden"
#: fortran/cpp.c:540 fortran/cpp.c:551 fortran/cpp.c:649
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "opening output file %s: %s"
-msgstr "Ausgabedatei »%s« wird geöffnet: %m"
+msgstr "Ausgabedatei »%s« wird geöffnet: %s"
#: fortran/data.c:65
#, gcc-internal-format, gfc-internal-format
@@ -33441,9 +33441,9 @@ msgid "failure to simplify substring reference in DATA statement at %L"
msgstr "Fehlschlag bei Vereinfachung der Teil-Zeichenketten-Referenz in DATA-Anweisung bei %L"
#: fortran/data.c:158
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Initialization string starting at %L was truncated to fit the variable (%d/%d)"
-msgstr "Initialisierungszeichenkette abgeschnitten um an Variable bei %L anzupassen"
+msgstr "Initialisierungszeichenkette abgeschnitten, um an Variable bei %L anzupassen (%d/%d)"
#: fortran/data.c:244
#, gcc-internal-format, gfc-internal-format
@@ -33501,9 +33501,9 @@ msgid "Bad INTENT specification at %C"
msgstr "Falsche INTENT-Spezifikation bei %C"
#: fortran/decl.c:671
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2003: deferred type parameter at %C"
-msgstr "Fortran 2003: VALUE-Anweisung bei %C"
+msgstr "Fortran 2003: Parameter mit zurückgestelltem Typ bei %C"
#: fortran/decl.c:708
#, gcc-internal-format, gfc-internal-format
@@ -33511,9 +33511,9 @@ msgid "Conflict in attributes of function argument at %C"
msgstr "Konflikt in Attributen des Funktionsarguments bei %C"
#: fortran/decl.c:733
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Obsolescent feature: Old-style character length at %C"
-msgstr "Veraltet: Arithmetische IF-Anweisung bei %C"
+msgstr "Veraltete Funktion: Zeichenlänge alten Stils bei %C"
#: fortran/decl.c:765
#, gcc-internal-format, gfc-internal-format
@@ -33541,7 +33541,7 @@ msgid "Procedure '%s' at %L must have the BIND(C) attribute to be C interoperabl
msgstr "Prozedur »%s« bei %L muss das BIND(C)-Attribut haben, um mit C interoperabel zu sein"
#: fortran/decl.c:1011
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Type '%s' at %L is a parameter to the BIND(C) procedure '%s' but is not C interoperable because derived type '%s' is not C interoperable"
msgstr "Typ »%s« bei %L ist ein Parameter für die BIND(C)-Prozedur »%s«, jedoch nicht interoperabel mit C, da der abgeleitete Typ »%s« nicht mit C interoperabel ist"
@@ -33611,14 +33611,14 @@ msgid "Variable '%s' at %C with an initializer already appears in a DATA stateme
msgstr "Variable »%s« bei %C mit Initialisierung tritt bereits in einer DATA-Anweisung auf"
#: fortran/decl.c:1409
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Can't initialize implied-shape array at %L with scalar"
-msgstr "mehrdimensionales Feld kann nicht initialisiert werden"
+msgstr "Feld mit implizierter Form bei %L kann nicht mit Skalar initialisiert werden"
#: fortran/decl.c:1427
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Non-constant lower bound in implied-shape declaration at %L"
-msgstr "Syntaxfehler in Daten-Deklaration bei %C"
+msgstr "Nicht-konstante untere Grenze in Deklaration mit impliziter Form bei %L"
#: fortran/decl.c:1522
#, gcc-internal-format, gfc-internal-format
@@ -33656,24 +33656,24 @@ msgid "Initialization of pointer at %C is not allowed in a PURE procedure"
msgstr "Initialisierung des Zeigers bei %C ist nicht in einer PURE-Prozedur erlaubt"
#: fortran/decl.c:1709
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Error in pointer initialization at %C"
-msgstr "Erweiterung: Initialisierung im alten Stil bei %C"
+msgstr "Fehler in Zeigerinitialisierung bei %C"
#: fortran/decl.c:1716
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: non-NULL pointer initialization at %C"
-msgstr "Fortran 2003: Nichtganzzahliger Exponent in einem Initialisierungsausdruck bei %L"
+msgstr "Fortran 2008: Nicht-NULL-Zeigerinitialisierung bei %C"
#: fortran/decl.c:1777
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Non-PARAMETER symbol '%s' at %L can't be implied-shape"
-msgstr "CHARACTER(*)-Funktion »%s« bei %L kann nicht Zeiger-wertig sein"
+msgstr "Nicht-PARAMETER-Symbol »%s« bei %L kann nicht implizite Form haben"
#: fortran/decl.c:1788
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: Implied-shape array at %L"
-msgstr "Fortran 2003: IOMSG-Markierung bei %L"
+msgstr "Fortran 2008: Feld mit impliziter Form bei %L"
#: fortran/decl.c:1852 fortran/decl.c:6247
#, gcc-internal-format, gfc-internal-format
@@ -33751,9 +33751,9 @@ msgid "Kind %d not supported for type %s at %C"
msgstr "Die Art %d wird für Typ %s bei %C nicht unterstützt"
#: fortran/decl.c:2196
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "C kind type parameter is for type %s but type at %L is %s"
-msgstr "Parameter nach C-Art ist für Typ %s, aber Symbol »%s« bei %L ist vom Typ %s"
+msgstr "Typ-Parameter nach C-Art ist für Typ %s, aber Typ bei %L ist %s"
#: fortran/decl.c:2205
#, gcc-internal-format, gfc-internal-format
@@ -33782,24 +33782,24 @@ msgstr "Bei %C verwendeter BYTE-Typ ist auf der Zielmaschine nicht verfügbar"
#: fortran/decl.c:2526 fortran/decl.c:2557 fortran/decl.c:2587
#: fortran/decl.c:2681
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: TYPE with intrinsic-type-spec at %C"
-msgstr "Fortran 2003: VOLATILE-Attribut bei %C"
+msgstr "Fortran 2008: TYPE mit intrinsischer Typspezifikation bei %C"
#: fortran/decl.c:2582
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Extension: DOUBLE COMPLEX at %C"
-msgstr "Erweiterung: BYTE-Typ bei %C"
+msgstr "Erweiterung: DOUBLE COMPLEX bei %C"
#: fortran/decl.c:2620
#, gcc-internal-format, gfc-internal-format
msgid "Unlimited polymorphism at %C not yet supported"
-msgstr ""
+msgstr "Unbegrenzter Polymorphismus bei %C wird noch nicht unterstützt"
#: fortran/decl.c:2629
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2003: CLASS statement at %C"
-msgstr "Fortran 2003: FLUSH-Anweisung bei %C"
+msgstr "Fortran 2003: CLASS-Anweisung bei %C"
#: fortran/decl.c:2652 fortran/decl.c:2661 fortran/decl.c:2995
#: fortran/decl.c:3003
@@ -33853,9 +33853,9 @@ msgid "Syntax error in IMPORT statement at %C"
msgstr "Syntaxfehler in IMPORT-Anweisung bei %C"
#: fortran/decl.c:3344
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Missing codimension specification at %C"
-msgstr "Fehlende Dimensionsangabe bei %C"
+msgstr "Fehlende Kodimensionsangabe bei %C"
#: fortran/decl.c:3346
#, gcc-internal-format, gfc-internal-format
@@ -33888,14 +33888,14 @@ msgid "%s attribute at %L is not allowed outside of the specification part of a
msgstr "Attribut %s bei %L ist außerhalb des Spezifikationsabschnitts eines Moduls nicht erlaubt"
#: fortran/decl.c:3502
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2003: ASYNCHRONOUS attribute at %C"
-msgstr "Fortran 2003: VALUE-Attribut bei %C"
+msgstr "Fortran 2003: ASYNCHRONOUS-Attribut bei %C"
#: fortran/decl.c:3515
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: CONTIGUOUS attribute at %C"
-msgstr "Fortran 2003: VOLATILE-Attribut bei %C"
+msgstr "Fortran 2008: CONTIGUOUS-Attribut bei %C"
#: fortran/decl.c:3561 fortran/decl.c:6535
#, gcc-internal-format, gfc-internal-format
@@ -33997,14 +33997,14 @@ msgid "Syntax error in data declaration at %C"
msgstr "Syntaxfehler in Daten-Deklaration bei %C"
#: fortran/decl.c:4185
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: IMPURE procedure at %C"
-msgstr "Fortran 2003: \"USE :: module\" bei %C"
+msgstr "Fortran 2008: IMPURE-Prozedur bei %C"
#: fortran/decl.c:4198
#, gcc-internal-format, gfc-internal-format
msgid "PURE and IMPURE must not appear both at %C"
-msgstr ""
+msgstr "PURE und IMPURE dürfen bei %C nicht gleichzeitig stehen"
#: fortran/decl.c:4304
#, gcc-internal-format, gfc-internal-format
@@ -34032,9 +34032,9 @@ msgid "Unexpected junk after function declaration at %C"
msgstr "Unerwartete Angaben hinter Funktionsdeklaration bei %C"
#: fortran/decl.c:4471 fortran/decl.c:5500
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: BIND(C) attribute at %L may not be specified for an internal procedure"
-msgstr "Erweiterung: BIND(C)-Attribut bei %L kann nicht für eine interne Prozedur angegeben werden"
+msgstr "Fortran 2008: BIND(C)-Attribut bei %L kann nicht für eine interne Prozedur angegeben werden"
#: fortran/decl.c:4615
#, gcc-internal-format, gfc-internal-format
@@ -34067,9 +34067,9 @@ msgid "Dummy procedure at %C may not have BIND(C) attribute with NAME"
msgstr "Scheinprozedur bei %C kann kein BIND(C)-Attribut mit NAME haben"
#: fortran/decl.c:4725
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Procedure '%s' at %L already has basic type of %s"
-msgstr "Symbol »%s« bei %L hat bereits grundlegenden Typen %s"
+msgstr "Prozedur »%s« bei %L hat bereits grundlegenden Typen %s"
#: fortran/decl.c:4773 fortran/decl.c:4940 fortran/decl.c:7978
#, gcc-internal-format, gfc-internal-format
@@ -34077,24 +34077,24 @@ msgid "Syntax error in PROCEDURE statement at %C"
msgstr "Syntaxfehler in PROCEDURE-Anweisung bei %C"
#: fortran/decl.c:4822 fortran/decl.c:7879
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected '::' after binding-attributes at %C"
-msgstr "Beendenden Namen bei %C erwartet"
+msgstr "»::« nach Bindeattributen bei %C erwartet"
#: fortran/decl.c:4829
#, gcc-internal-format, gfc-internal-format
msgid "NOPASS or explicit interface required at %C"
-msgstr ""
+msgstr "NOPASS oder explizite Schnittstelle bei %C erforderlich"
#: fortran/decl.c:4833
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2003: Procedure pointer component at %C"
-msgstr "Fortran 2003: Modul-Eigenschaft in USE-Anweisung bei %C"
+msgstr "Fortran 2003: Prozedurzeiger-Komponente bei %C"
#: fortran/decl.c:4897
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Syntax error in procedure pointer component at %C"
-msgstr "Syntaxfehler in Strukturkonstruktor bei %C"
+msgstr "Syntaxfehler in Prozedurzeiger-Komponente bei %C"
#: fortran/decl.c:4914
#, gcc-internal-format, gfc-internal-format
@@ -34119,9 +34119,9 @@ msgid "BIND(C) attribute at %L can only be used for variables or common blocks"
msgstr "BIND(C)-Attribut bei %L kann nur für Variablen oder gemeinsame Blöcke verwendet werden"
#: fortran/decl.c:5190
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008 obsolescent feature: ENTRY statement at %C"
-msgstr "Fortran 2003: Modul-Eigenschaft in USE-Anweisung bei %C"
+msgstr "Fortran 2008: Veraltete Funktion: ENTRY-Anweisung bei %C"
#: fortran/decl.c:5200
#, gcc-internal-format, gfc-internal-format
@@ -34229,9 +34229,9 @@ msgid "Unexpected END statement at %C"
msgstr "Unerwartete END-Anweisung bei %C"
#: fortran/decl.c:5875
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: END statement instead of %s statement at %L"
-msgstr "Fortran 2003: Modul-Eigenschaft in USE-Anweisung bei %C"
+msgstr "Fortran 2008: END-Anweisung statt %s-Anweisung bei %L"
#. We would have required END [something].
#: fortran/decl.c:5883
@@ -34270,9 +34270,9 @@ msgid "Dimensions specified for %s at %L after its initialisation"
msgstr "Für %s bei %L wurden Dimensionen nach dessen Initialisierung angegeben"
#: fortran/decl.c:6019
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Missing array specification at %L in CODIMENSION statement"
-msgstr "Fehlende Feldspezifikation bei %L in DIMENSION-Anweisung"
+msgstr "Feldspezifikation bei %L in CODIMENSION-Anweisung fehlt"
#: fortran/decl.c:6028
#, gcc-internal-format, gfc-internal-format
@@ -34322,12 +34322,12 @@ msgstr "»,« oder Ende der Anweisung bei %C erwartet"
#: fortran/decl.c:6305
#, gcc-internal-format, gfc-internal-format
msgid "INTENT is not allowed inside of BLOCK at %C"
-msgstr ""
+msgstr "INTENT ist in BLOCK bei %C nicht erlaubt"
#: fortran/decl.c:6337
#, gcc-internal-format, gfc-internal-format
msgid "OPTIONAL is not allowed inside of BLOCK at %C"
-msgstr ""
+msgstr "OPTIONAL ist in BLOCK bei %C nicht erlaubt"
#: fortran/decl.c:6356
#, gcc-internal-format, gfc-internal-format
@@ -34335,9 +34335,9 @@ msgid "Cray pointer declaration at %C requires -fcray-pointer flag"
msgstr "Cray-Zeiger-Deklaration bei %C benötigt den Schalter -fcray-pointer"
#: fortran/decl.c:6395
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: CONTIGUOUS statement at %C"
-msgstr "Fortran 2003: FLUSH-Anweisung bei %C"
+msgstr "Fortran 2008: CONTIGUOUS-Anweisung bei %C"
#: fortran/decl.c:6486
#, gcc-internal-format, gfc-internal-format
@@ -34412,7 +34412,7 @@ msgstr "Syntaxfehler in SAVE-Anweisung bei %C"
#: fortran/decl.c:6835
#, gcc-internal-format, gfc-internal-format
msgid "VALUE is not allowed inside of BLOCK at %C"
-msgstr ""
+msgstr "VALUE ist in BLOCK bei %C nicht erlaubt"
#: fortran/decl.c:6839
#, gcc-internal-format, gfc-internal-format
@@ -34432,7 +34432,7 @@ msgstr "Fortran 2003: VOLATILE-Anweisung bei %C"
#: fortran/decl.c:6914
#, gcc-internal-format, gfc-internal-format
msgid "Specifying VOLATILE for coarray variable '%s' at %C, which is use-/host-associated"
-msgstr ""
+msgstr "VOLATILE für Coarray-Variable »%s« bei »%C« angegeben, die use-/host-assoziiert ist"
#: fortran/decl.c:6940
#, gcc-internal-format, gfc-internal-format
@@ -34440,14 +34440,14 @@ msgid "Syntax error in VOLATILE statement at %C"
msgstr "Syntaxfehler in VOLATILE-Anweisung bei %C"
#: fortran/decl.c:6951
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2003: ASYNCHRONOUS statement at %C"
-msgstr "Fortran 2003: VALUE-Anweisung bei %C"
+msgstr "Fortran 2003: ASYNCHRONOUS-Anweisung bei %C"
#: fortran/decl.c:6993
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Syntax error in ASYNCHRONOUS statement at %C"
-msgstr "Syntaxfehler in VALUE-Anweisung bei %C"
+msgstr "Syntaxfehler in ASYNCHRONOUS-Anweisung bei %C"
#: fortran/decl.c:7017
#, gcc-internal-format, gfc-internal-format
@@ -34455,39 +34455,39 @@ msgid "MODULE PROCEDURE at %C must be in a generic module interface"
msgstr "MODULE PROCEDURE bei %C muss in einer generischen Modulschnittstelle sein"
#: fortran/decl.c:7042
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: double colon in MODULE PROCEDURE statement at %L"
-msgstr "Fortran 2003: PROCEDURE-Anweisung bei %C"
+msgstr "Fortran 2008: »::« in MODULE PROCEDURE-Anweisung bei %L"
#: fortran/decl.c:7076
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Intrinsic procedure at %L cannot be a MODULE PROCEDURE"
-msgstr "Intrinsische Prozedur »%s« ist in PROCEDURE-Anweisung bei %C nicht erlaubt"
+msgstr "Intrinsische Prozedur bei %L kann keine MODULE PROCEDURE sein"
#: fortran/decl.c:7125
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Ambiguous symbol in TYPE definition at %C"
-msgstr "»::« in TYPE-Definition bei %C erwartet"
+msgstr "Mehrdeutiges Symbol in TYPE-Definition bei %C"
#: fortran/decl.c:7131
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "No such symbol in TYPE definition at %C"
-msgstr "»::« in TYPE-Definition bei %C erwartet"
+msgstr "Kein solches Symbol in TYPE-Definition bei %C"
#: fortran/decl.c:7137
#, gcc-internal-format, gfc-internal-format
msgid "'%s' in EXTENDS expression at %C is not a derived type"
-msgstr ""
+msgstr "»%s« in EXTENDS-Ausdruck bei %C ist kein abgeleiteter Typ"
#: fortran/decl.c:7144
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' cannot be extended at %C because it is BIND(C)"
-msgstr "Abgeleiteter Typ »%s« bei %L kann nicht das SEQUENCE-Attribut haben, da es BIND(C) ist"
+msgstr "»%s« kann bei %C nicht erweitert werden, da es BIND(C) ist"
#: fortran/decl.c:7151
#, gcc-internal-format, gfc-internal-format
msgid "'%s' cannot be extended at %C because it is a SEQUENCE type"
-msgstr ""
+msgstr "»%s« kann bei %C nicht erweitert werden, da es ein SEQUENCE-Typ ist"
#: fortran/decl.c:7174
#, gcc-internal-format, gfc-internal-format
@@ -34500,9 +34500,9 @@ msgid "Derived type at %C can only be PUBLIC in the specification part of a modu
msgstr "Abgeleiteter Typ bei %C kann nur PUBLIC im Spezifikationsteil eines Moduls sein"
#: fortran/decl.c:7207
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2003: ABSTRACT type at %C"
-msgstr "Fortran 2003: ABSTRACT INTERFACE bei %C"
+msgstr "Fortran 2003: ABSTRACT-Typ bei %C"
#: fortran/decl.c:7271
#, gcc-internal-format, gfc-internal-format
@@ -34555,159 +34555,159 @@ msgid "Syntax error in ENUMERATOR definition at %C"
msgstr "Syntaxfehler in ENUMERATOR-Definition bei %C"
#: fortran/decl.c:7644 fortran/decl.c:7659
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Duplicate access-specifier at %C"
-msgstr "Doppelte Spezifikation %s bei %C"
+msgstr "Doppelte Zugriffsspezifikation bei %C"
#: fortran/decl.c:7679
#, gcc-internal-format, gfc-internal-format
msgid "Binding attributes already specify passing, illegal NOPASS at %C"
-msgstr ""
+msgstr "Bindeattribute legen bereits Durchleitung fest, unzulässiges NOPASS bei %C"
#: fortran/decl.c:7699
#, gcc-internal-format, gfc-internal-format
msgid "Binding attributes already specify passing, illegal PASS at %C"
-msgstr ""
+msgstr "Bindeattribute legen bereits Durchleitung fest, unzulässiges PASS bei %C"
#: fortran/decl.c:7726
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Duplicate POINTER attribute at %C"
-msgstr "Doppeltes Attribut %s bei %L"
+msgstr "Doppeltes POINTER-Attribut bei %C"
#: fortran/decl.c:7744
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Duplicate NON_OVERRIDABLE at %C"
-msgstr "VARIABLE bei %C erwartet"
+msgstr "Doppeltes NON_OVERRIDABLE bei %C"
#: fortran/decl.c:7760
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Duplicate DEFERRED at %C"
-msgstr "Doppelte SEQUENCE-Anweisung bei %C"
+msgstr "Doppeltes DEFERRED bei %C"
#: fortran/decl.c:7773
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected access-specifier at %C"
-msgstr "Namenlose Schnittstelle bei %C erwartet"
+msgstr "Zugriffsspezifikation bei %C erwartet"
#: fortran/decl.c:7775
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected binding attribute at %C"
-msgstr "Beendenden Namen bei %C erwartet"
+msgstr "Bindeattribut bei %C erwartet"
#: fortran/decl.c:7783
#, gcc-internal-format, gfc-internal-format
msgid "NON_OVERRIDABLE and DEFERRED can't both appear at %C"
-msgstr ""
+msgstr "NON_OVERRIDABLE und DEFERRED können nicht gleichzeitig bei %C auftreten"
#: fortran/decl.c:7795
#, gcc-internal-format, gfc-internal-format
msgid "POINTER attribute is required for procedure pointer component at %C"
-msgstr ""
+msgstr "POINTER-Attribut ist für Prozedurzeiger-Komponente bei %C erforderlich"
#: fortran/decl.c:7837
#, gcc-internal-format, gfc-internal-format
msgid "Interface-name expected after '(' at %C"
-msgstr ""
+msgstr "Schnittstellenname nach »(« bei %C erforderlich"
#: fortran/decl.c:7843
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "')' expected at %C"
-msgstr "»)« erwartet"
+msgstr "»)« bei %C erwartet"
#: fortran/decl.c:7863
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Interface must be specified for DEFERRED binding at %C"
-msgstr "Syntaxfehler in NAME=-Spezifikation für Bindungsmarke bei %C"
+msgstr "Schnittstelle muss für DEFERRED-Bindung bei %C angegeben werden"
#: fortran/decl.c:7868
#, gcc-internal-format, gfc-internal-format
msgid "PROCEDURE(interface) at %C should be declared DEFERRED"
-msgstr ""
+msgstr "PROCEDURE(Schnittstelle) bei %C sollte als DEFERRED deklariert sein"
#: fortran/decl.c:7891
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected binding name at %C"
-msgstr "Beendenden Namen bei %C erwartet"
+msgstr "Bindungsname bei %C erwartet"
#: fortran/decl.c:7895
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Fortran 2008: PROCEDURE list at %C"
-msgstr "Fortran 2003: PROCEDURE-Anweisung bei %C"
+msgstr "Fortran 2008: PROCEDURE-Liste bei %C"
#: fortran/decl.c:7908
#, gcc-internal-format, gfc-internal-format
msgid "'=> target' is invalid for DEFERRED binding at %C"
-msgstr ""
+msgstr "»=> target« ist ungültig für DEFERRED-Bindung bei %C"
#: fortran/decl.c:7914
#, gcc-internal-format, gfc-internal-format
msgid "'::' needed in PROCEDURE binding with explicit target at %C"
-msgstr ""
+msgstr "»::« in PROCEDURE-Bindung mit explizitem Ziel bei %C erforderlich"
#: fortran/decl.c:7924
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected binding target after '=>' at %C"
-msgstr "Beendenden Namen bei %C erwartet"
+msgstr "Bindungsziel hinter »=>« bei %C erforderlich"
#: fortran/decl.c:7941
#, gcc-internal-format, gfc-internal-format
msgid "Type '%s' containing DEFERRED binding at %C is not ABSTRACT"
-msgstr ""
+msgstr "Typ »%s« mit DEFERRED-Bindung bei %C ist nicht ABSTRACT"
#: fortran/decl.c:7952
#, gcc-internal-format, gfc-internal-format
msgid "There is already a procedure with binding name '%s' for the derived type '%s' at %C"
-msgstr ""
+msgstr "Es gibt bereits eine Prozedur mit Bindungsname »%s« für den abgeleiteten Typ »%s« bei %C"
#: fortran/decl.c:8001
#, gcc-internal-format, gfc-internal-format
msgid "GENERIC at %C must be inside a derived-type CONTAINS"
-msgstr ""
+msgstr "GENERIC bei %C muss innerhalb eines CONTAINS eines abgeleiteten Typs sein"
#: fortran/decl.c:8021
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected '::' at %C"
-msgstr "»(« bei %C erwartet"
+msgstr "»::« bei %C erwartet"
#: fortran/decl.c:8033
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected generic name or operator descriptor at %C"
-msgstr "Feldindex erwartet bei %C"
+msgstr "Generischer Name oder Operatordeskriptor bei %C erwartet"
#: fortran/decl.c:8059
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected '=>' at %C"
-msgstr "»(« bei %C erwartet"
+msgstr "»=>« bei %C erwartet"
#: fortran/decl.c:8101
#, gcc-internal-format, gfc-internal-format
msgid "There's already a non-generic procedure with binding name '%s' for the derived type '%s' at %C"
-msgstr ""
+msgstr "Es gibt bereits eine nicht-generische Prozedur mit Bindungsname »%s« für den abgeleiteten Typ »%s« bei %C"
#: fortran/decl.c:8109
#, gcc-internal-format, gfc-internal-format
msgid "Binding at %C must have the same access as already defined binding '%s'"
-msgstr ""
+msgstr "Bindung bei %C muss den selben Zugriff wie bereits definierte Bindung »%s« haben"
#: fortran/decl.c:8158
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "Expected specific binding name at %C"
-msgstr "Beendenden Namen bei %C erwartet"
+msgstr "Spezifischer Bindungsname bei %C erwartet"
#: fortran/decl.c:8168
-#, fuzzy, gcc-internal-format, gfc-internal-format
+#, gcc-internal-format, gfc-internal-format
msgid "'%s' already defined as specific binding for the generic '%s' at %C"
-msgstr "Es gibt keine spezifische Funktion für das allgemeine »%s« bei %L"
+msgstr "»%s« bereits als spezifische Bindung für das allgemeine »%s« bei %C definiert"
#: fortran/decl.c:8184
#, gcc-internal-format, gfc-internal-format
msgid "Junk after GENERIC binding at %C"
-msgstr ""
+msgstr "Ausschuss hinter GENERIC-Bindung bei %C"
#: fortran/decl.c:8219
#, gcc-internal-format, gfc-internal-format
msgid "FINAL declaration at %C must be inside a derived type CONTAINS section"
-msgstr ""
+msgstr "FINAL-Deklaration bei %C muss innerhalb eines CONTAINS-Abschnitts eines abgeleiteten Typs stehen"
#: fortran/decl.c:8230
#, fuzzy, gcc-internal-format, gfc-internal-format
diff --git a/gcc/profile.c b/gcc/profile.c
index 893e2cd17c7..41108394e98 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -437,6 +437,39 @@ read_profile_edge_counts (gcov_type *exec_counts)
return num_edges;
}
+#define OVERLAP_BASE 10000
+
+/* Compare the static estimated profile to the actual profile, and
+ return the "degree of overlap" measure between them.
+
+ Degree of overlap is a number between 0 and OVERLAP_BASE. It is
+ the sum of each basic block's minimum relative weights between
+ two profiles. And overlap of OVERLAP_BASE means two profiles are
+ identical. */
+
+static int
+compute_frequency_overlap (void)
+{
+ gcov_type count_total = 0, freq_total = 0;
+ int overlap = 0;
+ basic_block bb;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ {
+ count_total += bb->count;
+ freq_total += bb->frequency;
+ }
+
+ if (count_total == 0 || freq_total == 0)
+ return 0;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ overlap += MIN (bb->count * OVERLAP_BASE / count_total,
+ bb->frequency * OVERLAP_BASE / freq_total);
+
+ return overlap;
+}
+
/* Compute the branch probabilities for the various branches.
Annotate them accordingly.
@@ -607,7 +640,13 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
}
}
if (dump_file)
- dump_flow_info (dump_file, dump_flags);
+ {
+ int overlap = compute_frequency_overlap ();
+ dump_flow_info (dump_file, dump_flags);
+ fprintf (dump_file, "Static profile overlap: %d.%d%%\n",
+ overlap / (OVERLAP_BASE / 100),
+ overlap % (OVERLAP_BASE / 100));
+ }
total_num_passes += passes;
if (dump_file)
diff --git a/gcc/regrename.c b/gcc/regrename.c
index bfff1033018..1823558f451 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -39,6 +39,8 @@
#include "tree-pass.h"
#include "df.h"
#include "target.h"
+#include "emit-rtl.h"
+#include "regrename.h"
/* This file implements the RTL register renaming pass of the compiler. It is
a semi-local pass whose goal is to maximize the usage of the register file
@@ -73,47 +75,6 @@
#error "Use a different bitmap implementation for untracked_operands."
#endif
-/* We keep linked lists of DU_HEAD structures, each of which describes
- a chain of occurrences of a reg. */
-struct du_head
-{
- /* The next chain. */
- struct du_head *next_chain;
- /* The first and last elements of this chain. */
- struct du_chain *first, *last;
- /* Describe the register being tracked, register number and count. */
- unsigned regno;
- int nregs;
-
- /* A unique id to be used as an index into the conflicts bitmaps. */
- unsigned id;
- /* A bitmap to record conflicts with other chains. */
- bitmap_head conflicts;
- /* Conflicts with untracked hard registers. */
- HARD_REG_SET hard_conflicts;
-
- /* Nonzero if the chain crosses a call. */
- unsigned int need_caller_save_reg:1;
- /* Nonzero if the register is used in a way that prevents renaming,
- such as the SET_DEST of a CALL_INSN or an asm operand that used
- to be a hard register. */
- unsigned int cannot_rename:1;
-};
-
-/* This struct describes a single occurrence of a register. */
-struct du_chain
-{
- /* Links to the next occurrence of the register. */
- struct du_chain *next_use;
-
- /* The insn where the register appears. */
- rtx insn;
- /* The location inside the insn. */
- rtx *loc;
- /* The register class required by the insn at this location. */
- ENUM_BITFIELD(reg_class) cl : 16;
-};
-
enum scan_actions
{
terminate_write,
@@ -144,15 +105,14 @@ static int this_tick = 0;
static struct obstack rename_obstack;
-static void do_replace (struct du_head *, int);
+/* If nonnull, the code calling into the register renamer requested
+ information about insn operands, and we store it here. */
+VEC(insn_rr_info, heap) *insn_rr;
+
static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
enum op_type);
static bool build_def_use (basic_block);
-typedef struct du_head *du_head_p;
-DEF_VEC_P (du_head_p);
-DEF_VEC_ALLOC_P (du_head_p, heap);
-
/* The id to be given to the next opened chain. */
static unsigned current_id;
@@ -173,10 +133,15 @@ static HARD_REG_SET live_in_chains;
between this and live_in_chains is empty. */
static HARD_REG_SET live_hard_regs;
+/* Set while scanning RTL if INSN_RR is nonnull, i.e. if the current analysis
+ is for a caller that requires operand data. Used in
+ record_operand_use. */
+static operand_rr_info *cur_operand;
+
/* Return the chain corresponding to id number ID. Take into account that
chains may have been merged. */
-static du_head_p
-chain_from_id (unsigned int id)
+du_head_p
+regrename_chain_from_id (unsigned int id)
{
du_head_p first_chain = VEC_index (du_head_p, id_to_chain, id);
du_head_p chain = first_chain;
@@ -237,6 +202,19 @@ mark_conflict (struct du_head *chains, unsigned id)
}
}
+/* Examine cur_operand, and if it is nonnull, record information about the
+ use THIS_DU which is part of the chain HEAD. */
+
+static void
+record_operand_use (struct du_head *head, struct du_chain *this_du)
+{
+ if (cur_operand == NULL)
+ return;
+ gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
+ cur_operand->heads[cur_operand->n_chains] = head;
+ cur_operand->chains[cur_operand->n_chains++] = this_du;
+}
+
/* Create a new chain for THIS_NREGS registers starting at THIS_REGNO,
and record its occurrence in *LOC, which is being written to in INSN.
This access requires a register of class CL. */
@@ -299,6 +277,7 @@ create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
this_du->loc = loc;
this_du->insn = insn;
this_du->cl = cl;
+ record_operand_use (head, this_du);
return head;
}
@@ -313,7 +292,7 @@ merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head)
IOR_HARD_REG_SET (*pset, head->hard_conflicts);
EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi)
{
- du_head_p other = chain_from_id (i);
+ du_head_p other = regrename_chain_from_id (i);
unsigned j = other->nregs;
gcc_assert (other != head);
while (j-- > 0)
@@ -368,6 +347,69 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
return true;
}
+/* For the chain THIS_HEAD, compute and return the best register to
+ rename to. SUPER_CLASS is the superunion of register classes in
+ the chain. UNAVAILABLE is a set of registers that cannot be used.
+ OLD_REG is the register currently used for the chain. */
+
+int
+find_best_rename_reg (du_head_p this_head, enum reg_class super_class,
+ HARD_REG_SET *unavailable, int old_reg)
+{
+ bool has_preferred_class;
+ enum reg_class preferred_class;
+ int pass;
+ int best_new_reg = old_reg;
+
+ /* Further narrow the set of registers we can use for renaming.
+ If the chain needs a call-saved register, mark the call-used
+ registers as unavailable. */
+ if (this_head->need_caller_save_reg)
+ IOR_HARD_REG_SET (*unavailable, call_used_reg_set);
+
+ /* Mark registers that overlap this chain's lifetime as unavailable. */
+ merge_overlapping_regs (unavailable, this_head);
+
+ /* Compute preferred rename class of super union of all the classes
+ in the chain. */
+ preferred_class
+ = (enum reg_class) targetm.preferred_rename_class (super_class);
+
+ /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
+ over registers that belong to PREFERRED_CLASS and try to find the
+ best register within the class. If that failed, we iterate in
+ the second pass over registers that don't belong to the class.
+ If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
+ ascending order without any preference. */
+ has_preferred_class = (preferred_class != NO_REGS);
+ for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
+ {
+ int new_reg;
+ for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
+ {
+ if (has_preferred_class
+ && (pass == 0)
+ != TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ new_reg))
+ continue;
+
+ /* In the first pass, we force the renaming of registers that
+ don't belong to PREFERRED_CLASS to registers that do, even
+ though the latters were used not very long ago. */
+ if (check_new_reg_p (old_reg, new_reg, this_head,
+ *unavailable)
+ && ((pass == 0
+ && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ best_new_reg))
+ || tick[best_new_reg] > tick[new_reg]))
+ best_new_reg = new_reg;
+ }
+ if (pass == 0 && best_new_reg != old_reg)
+ break;
+ }
+ return best_new_reg;
+}
+
/* Perform register renaming on the current function. */
static void
rename_chains (void)
@@ -390,22 +432,16 @@ rename_chains (void)
FOR_EACH_VEC_ELT (du_head_p, id_to_chain, i, this_head)
{
- int new_reg, best_new_reg, best_nregs;
+ int best_new_reg;
int n_uses;
struct du_chain *tmp;
HARD_REG_SET this_unavailable;
int reg = this_head->regno;
- int pass;
enum reg_class super_class = NO_REGS;
- enum reg_class preferred_class;
- bool has_preferred_class;
if (this_head->cannot_rename)
continue;
- best_new_reg = reg;
- best_nregs = this_head->nregs;
-
if (fixed_regs[reg] || global_regs[reg]
#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
|| (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM)
@@ -437,56 +473,8 @@ rename_chains (void)
if (n_uses < 2)
continue;
- /* Further narrow the set of registers we can use for renaming.
- If the chain needs a call-saved register, mark the call-used
- registers as unavailable. */
- if (this_head->need_caller_save_reg)
- IOR_HARD_REG_SET (this_unavailable, call_used_reg_set);
-
- /* And mark registers that overlap its lifetime as unavailable. */
- merge_overlapping_regs (&this_unavailable, this_head);
-
- /* Compute preferred rename class of super union of all the classes
- in the chain. */
- preferred_class
- = (enum reg_class) targetm.preferred_rename_class (super_class);
-
- /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
- over registers that belong to PREFERRED_CLASS and try to find the
- best register within the class. If that failed, we iterate in
- the second pass over registers that don't belong to the class.
- If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
- ascending order without any preference. */
- has_preferred_class = (preferred_class != NO_REGS);
- for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
- {
- for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
- {
- if (has_preferred_class
- && ((pass == 0) != TEST_HARD_REG_BIT
- (reg_class_contents[preferred_class], new_reg)))
- continue;
-
- /* In the first pass, we force the renaming of registers that
- don't belong to PREFERRED_CLASS to registers that do, even
- though the latters were used not very long ago. */
- if (check_new_reg_p (reg, new_reg, this_head,
- this_unavailable)
- && ((pass == 0
- && (!TEST_HARD_REG_BIT
- (reg_class_contents[preferred_class],
- best_new_reg)))
- || tick[best_new_reg] > tick[new_reg]))
- {
- enum machine_mode mode
- = GET_MODE (*this_head->first->loc);
- best_new_reg = new_reg;
- best_nregs = hard_regno_nregs[new_reg][mode];
- }
- }
- if (pass == 0 && best_new_reg != reg)
- break;
- }
+ best_new_reg = find_best_rename_reg (this_head, super_class,
+ &this_unavailable, reg);
if (dump_file)
{
@@ -507,9 +495,7 @@ rename_chains (void)
if (dump_file)
fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
- do_replace (this_head, best_new_reg);
- this_head->regno = best_new_reg;
- this_head->nregs = best_nregs;
+ regrename_do_replace (this_head, best_new_reg);
tick[best_new_reg] = ++this_tick;
df_set_regs_ever_live (best_new_reg, true);
}
@@ -675,8 +661,8 @@ merge_chains (du_head_p c1, du_head_p c2)
/* Analyze the current function and build chains for renaming. */
-static void
-regrename_analyze (void)
+void
+regrename_analyze (bitmap bb_mask)
{
struct bb_rename_info *rename_info;
int i;
@@ -694,7 +680,10 @@ regrename_analyze (void)
{
struct bb_rename_info *ri = rename_info + i;
ri->bb = bb;
- bb->aux = ri;
+ if (bb_mask != NULL && !bitmap_bit_p (bb_mask, bb->index))
+ bb->aux = NULL;
+ else
+ bb->aux = ri;
i++;
}
@@ -735,6 +724,16 @@ regrename_analyze (void)
current_id = old_length;
bitmap_clear (&this_info->incoming_open_chains_set);
open_chains = NULL;
+ if (insn_rr != NULL)
+ {
+ rtx insn;
+ FOR_BB_INSNS (bb1, insn)
+ {
+ insn_rr_info *p = VEC_index (insn_rr_info, insn_rr,
+ INSN_UID (insn));
+ p->op_info = NULL;
+ }
+ }
continue;
}
@@ -798,7 +797,7 @@ regrename_analyze (void)
{
edge e;
edge_iterator ei;
- struct du_head *chain = chain_from_id (j);
+ struct du_head *chain = regrename_chain_from_id (j);
int n_preds_used = 0, n_preds_joined = 0;
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -825,7 +824,7 @@ regrename_analyze (void)
EXECUTE_IF_SET_IN_BITMAP (&src_ri->open_chains_set,
0, k, bi2)
{
- struct du_head *outgoing_chain = chain_from_id (k);
+ struct du_head *outgoing_chain = regrename_chain_from_id (k);
if (outgoing_chain->regno == chain->regno
&& outgoing_chain->nregs == chain->nregs)
@@ -863,7 +862,7 @@ regrename_analyze (void)
{
edge e;
edge_iterator ei;
- struct du_head *chain = chain_from_id (j);
+ struct du_head *chain = regrename_chain_from_id (j);
int n_succs_used = 0, n_succs_joined = 0;
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -888,7 +887,7 @@ regrename_analyze (void)
EXECUTE_IF_SET_IN_BITMAP (&dest_ri->incoming_open_chains_set,
0, k, bi2)
{
- struct du_head *incoming_chain = chain_from_id (k);
+ struct du_head *incoming_chain = regrename_chain_from_id (k);
if (incoming_chain->regno == chain->regno
&& incoming_chain->nregs == chain->nregs)
@@ -928,11 +927,12 @@ regrename_analyze (void)
bb->aux = NULL;
}
-static void
-do_replace (struct du_head *head, int reg)
+void
+regrename_do_replace (struct du_head *head, int reg)
{
struct du_chain *chain;
unsigned int base_regno = head->regno;
+ enum machine_mode mode;
for (chain = head->first; chain; chain = chain->next_use)
{
@@ -953,6 +953,10 @@ do_replace (struct du_head *head, int reg)
df_insn_rescan (chain->insn);
}
+
+ mode = GET_MODE (*head->first->loc);
+ head->regno = reg;
+ head->nregs = hard_regno_nregs[reg][mode];
}
@@ -1106,6 +1110,7 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
head->first = this_du;
else
head->last->next_use = this_du;
+ record_operand_use (head, this_du);
head->last = this_du;
}
/* Avoid adding the same location in a DEBUG_INSN multiple times,
@@ -1468,10 +1473,11 @@ restore_operands (rtx insn, int n_ops, rtx *old_operands, rtx *old_dups)
/* For each output operand of INSN, call scan_rtx to create a new
open chain. Do this only for normal or earlyclobber outputs,
- depending on EARLYCLOBBER. */
+ depending on EARLYCLOBBER. If INSN_INFO is nonnull, use it to
+ record information about the operands in the insn. */
static void
-record_out_operands (rtx insn, bool earlyclobber)
+record_out_operands (rtx insn, bool earlyclobber, insn_rr_info *insn_info)
{
int n_ops = recog_data.n_operands;
int alt = which_alternative;
@@ -1493,6 +1499,9 @@ record_out_operands (rtx insn, bool earlyclobber)
|| recog_op_alt[opn][alt].earlyclobber != earlyclobber)
continue;
+ if (insn_info)
+ cur_operand = insn_info->op_info + i;
+
prev_open = open_chains;
scan_rtx (insn, loc, cl, mark_write, OP_OUT);
@@ -1510,6 +1519,7 @@ record_out_operands (rtx insn, bool earlyclobber)
open_chains->cannot_rename = 1;
}
}
+ cur_operand = NULL;
}
/* Build def/use chain. */
@@ -1535,6 +1545,7 @@ build_def_use (basic_block bb)
int predicated;
enum rtx_code set_code = SET;
enum rtx_code clobber_code = CLOBBER;
+ insn_rr_info *insn_info = NULL;
/* Process the insn, determining its effect on the def-use
chains and live hard registers. We perform the following
@@ -1567,6 +1578,15 @@ build_def_use (basic_block bb)
n_ops = recog_data.n_operands;
untracked_operands = 0;
+ if (insn_rr != NULL)
+ {
+ insn_info = VEC_index (insn_rr_info, insn_rr, INSN_UID (insn));
+ insn_info->op_info = XOBNEWVEC (&rename_obstack, operand_rr_info,
+ recog_data.n_operands);
+ memset (insn_info->op_info, 0,
+ sizeof (operand_rr_info) * recog_data.n_operands);
+ }
+
/* Simplify the code below by rewriting things to reflect
matching constraints. Also promote OP_OUT to OP_INOUT in
predicated instructions, but only for register operands
@@ -1625,7 +1645,7 @@ build_def_use (basic_block bb)
/* Step 1b: Begin new chains for earlyclobbered writes inside
operands. */
- record_out_operands (insn, true);
+ record_out_operands (insn, true, insn_info);
/* Step 2: Mark chains for which we have reads outside operands
as unrenamable.
@@ -1674,11 +1694,14 @@ build_def_use (basic_block bb)
|| untracked_operands & (1 << opn))
continue;
+ if (insn_info)
+ cur_operand = i == opn ? insn_info->op_info + i : NULL;
if (recog_op_alt[opn][alt].is_address)
scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
else
scan_rtx (insn, loc, cl, mark_read, type);
}
+ cur_operand = NULL;
/* Step 3B: Record updates for regs in REG_INC notes, and
source regs in REG_FRAME_RELATED_EXPR notes. */
@@ -1729,7 +1752,7 @@ build_def_use (basic_block bb)
restore_operands (insn, n_ops, old_operands, old_dups);
/* Step 6b: Begin new chains for writes inside operands. */
- record_out_operands (insn, false);
+ record_out_operands (insn, false, insn_info);
/* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR
notes for update. */
@@ -1766,6 +1789,26 @@ build_def_use (basic_block bb)
return true;
}
+/* Initialize the register renamer. If INSN_INFO is true, ensure that
+ insn_rr is nonnull. */
+void
+regrename_init (bool insn_info)
+{
+ gcc_obstack_init (&rename_obstack);
+ insn_rr = NULL;
+ if (insn_info)
+ VEC_safe_grow_cleared (insn_rr_info, heap, insn_rr, get_max_uid ());
+}
+
+/* Free all global data used by the register renamer. */
+void
+regrename_finish (void)
+{
+ VEC_free (insn_rr_info, heap, insn_rr);
+ free_chain_data ();
+ obstack_free (&rename_obstack, NULL);
+}
+
/* Perform register renaming on the current function. */
static unsigned int
@@ -1776,14 +1819,13 @@ regrename_optimize (void)
df_analyze ();
df_set_flags (DF_DEFER_INSN_RESCAN);
- gcc_obstack_init (&rename_obstack);
+ regrename_init (false);
- regrename_analyze ();
+ regrename_analyze (NULL);
rename_chains ();
- free_chain_data ();
- obstack_free (&rename_obstack, NULL);
+ regrename_finish ();
return 0;
}
diff --git a/gcc/regrename.h b/gcc/regrename.h
new file mode 100644
index 00000000000..f3969a14fc2
--- /dev/null
+++ b/gcc/regrename.h
@@ -0,0 +1,101 @@
+/* This file contains definitions for the register renamer.
+ Copyright (C) 2011
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_REGRENAME_H
+#define GCC_REGRENAME_H
+
+/* We keep linked lists of DU_HEAD structures, each of which describes
+ a chain of occurrences of a reg. */
+struct du_head
+{
+ /* The next chain. */
+ struct du_head *next_chain;
+ /* The first and last elements of this chain. */
+ struct du_chain *first, *last;
+ /* Describes the register being tracked. */
+ unsigned regno;
+ int nregs;
+
+ /* A unique id to be used as an index into the conflicts bitmaps. */
+ unsigned id;
+ /* A bitmap to record conflicts with other chains. */
+ bitmap_head conflicts;
+ /* Conflicts with untracked hard registers. */
+ HARD_REG_SET hard_conflicts;
+
+ /* Nonzero if the chain crosses a call. */
+ unsigned int need_caller_save_reg:1;
+ /* Nonzero if the register is used in a way that prevents renaming,
+ such as the SET_DEST of a CALL_INSN or an asm operand that used
+ to be a hard register. */
+ unsigned int cannot_rename:1;
+};
+
+typedef struct du_head *du_head_p;
+DEF_VEC_P (du_head_p);
+DEF_VEC_ALLOC_P (du_head_p, heap);
+
+/* This struct describes a single occurrence of a register. */
+struct du_chain
+{
+ /* Links to the next occurrence of the register. */
+ struct du_chain *next_use;
+
+ /* The insn where the register appears. */
+ rtx insn;
+ /* The location inside the insn. */
+ rtx *loc;
+ /* The register class required by the insn at this location. */
+ ENUM_BITFIELD(reg_class) cl : 16;
+};
+
+/* This struct describes data gathered during regrename_analyze about
+ a single operand of an insn. */
+typedef struct
+{
+ /* The number of chains recorded for this operand. */
+ int n_chains;
+ /* Holds either the chain for the operand itself, or for the registers in
+ a memory operand. */
+ struct du_chain *chains[MAX_REGS_PER_ADDRESS];
+ struct du_head *heads[MAX_REGS_PER_ADDRESS];
+} operand_rr_info;
+
+/* A struct to hold a vector of operand_rr_info structures describing the
+ operands of an insn. */
+typedef struct
+{
+ operand_rr_info *op_info;
+} insn_rr_info;
+
+DEF_VEC_O (insn_rr_info);
+DEF_VEC_ALLOC_O (insn_rr_info, heap);
+
+extern VEC(insn_rr_info, heap) *insn_rr;
+
+extern void regrename_init (bool);
+extern void regrename_finish (void);
+extern void regrename_analyze (bitmap);
+extern du_head_p regrename_chain_from_id (unsigned int);
+extern int find_best_rename_reg (du_head_p, enum reg_class, HARD_REG_SET *,
+ int);
+extern void regrename_do_replace (du_head_p, int);
+
+#endif
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 179bf5fbdaf..f77a3a0f1d0 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -467,7 +467,7 @@ find_end_label (rtx kind)
/* The return we make may have delay slots too. */
rtx insn = gen_return ();
insn = emit_jump_insn (insn);
- JUMP_LABEL (insn) = ret_rtx;
+ set_return_jump_label (insn);
emit_barrier ();
if (num_delay_slots (insn) > 0)
obstack_ptr_grow (&unfilled_slots_obstack, insn);
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 567aff93668..1ffc7c26d7f 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -265,7 +265,8 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
when we access a component.
1 in a CALL_INSN if it is a sibling call.
1 in a SET that is for a return.
- In a CODE_LABEL, part of the two-bit alternate entry field. */
+ In a CODE_LABEL, part of the two-bit alternate entry field.
+ 1 in a CONCAT is VAL_EXPR_IS_COPIED in var-tracking.c. */
unsigned int jump : 1;
/* In a CODE_LABEL, part of the two-bit alternate entry field.
1 in a MEM if it cannot trap.
@@ -278,7 +279,9 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
constants pool.
1 in a CALL_INSN logically equivalent to ECF_CONST and TREE_READONLY.
1 in a NOTE, or EXPR_LIST for a const call.
- 1 in a JUMP_INSN of an annulling branch. */
+ 1 in a JUMP_INSN of an annulling branch.
+ 1 in a CONCAT is VAL_EXPR_IS_CLOBBERED in var-tracking.c.
+ 1 in a preserved VALUE is PRESERVED_VALUE_P in cselib.c. */
unsigned int unchanging : 1;
/* 1 in a MEM or ASM_OPERANDS expression if the memory reference is volatile.
1 in an INSN, CALL_INSN, JUMP_INSN, CODE_LABEL, BARRIER, or NOTE
@@ -290,7 +293,8 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
non-local label.
In a SYMBOL_REF, this flag is used for machine-specific purposes.
In a PREFETCH, this flag indicates that it should be considered a scheduling
- barrier. */
+ barrier.
+ 1 in a CONCAT is VAL_NEEDS_RESOLUTION in var-tracking.c. */
unsigned int volatil : 1;
/* 1 in a MEM referring to a field of an aggregate.
0 if the MEM was a variable or the result of a * operator in C;
@@ -311,19 +315,24 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
In a REG, this is not needed for that purpose, and used instead
in `leaf_renumber_regs_insn'.
1 in a SYMBOL_REF, means that emit_library_call
- has used it as the function. */
+ has used it as the function.
+ 1 in a CONCAT is VAL_HOLDS_TRACK_EXPR in var-tracking.c.
+ 1 in a VALUE or DEBUG_EXPR is VALUE_RECURSED_INTO in var-tracking.c. */
unsigned int used : 1;
/* 1 in an INSN or a SET if this rtx is related to the call frame,
either changing how we compute the frame address or saving and
restoring registers in the prologue and epilogue.
1 in a REG or MEM if it is a pointer.
1 in a SYMBOL_REF if it addresses something in the per-function
- constant string pool. */
+ constant string pool.
+ 1 in a VALUE is VALUE_CHANGED in var-tracking.c. */
unsigned frame_related : 1;
/* 1 in a REG or PARALLEL that is the current function's return value.
1 in a MEM if it refers to a scalar.
1 in a SYMBOL_REF for a weak symbol.
- 1 in a CALL_INSN logically equivalent to ECF_PURE and DECL_PURE_P. */
+ 1 in a CALL_INSN logically equivalent to ECF_PURE and DECL_PURE_P.
+ 1 in a CONCAT is VAL_EXPR_HAS_REVERSE in var-tracking.c.
+ 1 in a VALUE or DEBUG_EXPR is NO_LOC_P in var-tracking.c. */
unsigned return_val : 1;
/* The first element of the operands of this rtx.
@@ -2503,6 +2512,7 @@ extern int sibcall_epilogue_contains (const_rtx);
extern void mark_temp_addr_taken (rtx);
extern void update_temp_slot_address (rtx, rtx);
extern void maybe_copy_prologue_epilogue_insn (rtx, rtx);
+extern void set_return_jump_label (rtx);
/* In stmt.c */
extern void expand_null_return (void);
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index 4878460f882..dacee0b9e9b 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -1745,6 +1745,11 @@ update_target_availability (expr_t to, expr_t from, insn_t split_point)
else
EXPR_TARGET_AVAILABLE (to) = -1;
}
+ else if (EXPR_TARGET_AVAILABLE (from) == 0
+ && EXPR_LHS (from)
+ && REG_P (EXPR_LHS (from))
+ && REGNO (EXPR_LHS (to)) != REGNO (EXPR_LHS (from)))
+ EXPR_TARGET_AVAILABLE (to) = -1;
else
EXPR_TARGET_AVAILABLE (to) &= EXPR_TARGET_AVAILABLE (from);
}
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index f11faca740a..2af01aea99e 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -813,18 +813,12 @@ count_occurrences_1 (rtx *cur_rtx, void *arg)
{
rtx_search_arg_p p = (rtx_search_arg_p) arg;
- /* The last param FOR_GCSE is true, because otherwise it performs excessive
- substitutions like
- r8 = r33
- r16 = r33
- for the last insn it presumes r33 equivalent to r8, so it changes it to
- r33. Actually, there's no change, but it spoils debugging. */
- if (exp_equiv_p (*cur_rtx, p->x, 0, true))
- {
- /* Bail out if we occupy more than one register. */
- if (REG_P (*cur_rtx)
- && HARD_REGISTER_P (*cur_rtx)
- && hard_regno_nregs[REGNO(*cur_rtx)][GET_MODE (*cur_rtx)] > 1)
+ if (REG_P (*cur_rtx) && REGNO (*cur_rtx) == REGNO (p->x))
+ {
+ /* Bail out if mode is different or more than one register is used. */
+ if (GET_MODE (*cur_rtx) != GET_MODE (p->x)
+ || (HARD_REGISTER_P (*cur_rtx)
+ && hard_regno_nregs[REGNO(*cur_rtx)][GET_MODE (*cur_rtx)] > 1))
{
p->n = 0;
return 1;
@@ -837,7 +831,6 @@ count_occurrences_1 (rtx *cur_rtx, void *arg)
}
if (GET_CODE (*cur_rtx) == SUBREG
- && REG_P (p->x)
&& (!REG_P (SUBREG_REG (*cur_rtx))
|| REGNO (SUBREG_REG (*cur_rtx)) == REGNO (p->x)))
{
@@ -859,6 +852,7 @@ count_occurrences_equiv (rtx what, rtx where)
{
struct rtx_search_arg arg;
+ gcc_assert (REG_P (what));
arg.x = what;
arg.n = 0;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 06d60762011..af6439cd879 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -1685,120 +1685,21 @@ expand_return (tree retval)
expand_value_return (result_rtl);
/* If the result is an aggregate that is being returned in one (or more)
- registers, load the registers here. The compiler currently can't handle
- copying a BLKmode value into registers. We could put this code in a
- more general area (for use by everyone instead of just function
- call/return), but until this feature is generally usable it is kept here
- (and in expand_call). */
+ registers, load the registers here. */
else if (retval_rhs != 0
&& TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
&& REG_P (result_rtl))
{
- int i;
- unsigned HOST_WIDE_INT bitpos, xbitpos;
- unsigned HOST_WIDE_INT padding_correction = 0;
- unsigned HOST_WIDE_INT bytes
- = int_size_in_bytes (TREE_TYPE (retval_rhs));
- int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
- unsigned int bitsize
- = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD);
- rtx *result_pseudos = XALLOCAVEC (rtx, n_regs);
- rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
- rtx result_val = expand_normal (retval_rhs);
- enum machine_mode tmpmode, result_reg_mode;
-
- if (bytes == 0)
+ val = copy_blkmode_to_reg (GET_MODE (result_rtl), retval_rhs);
+ if (val)
{
- expand_null_return ();
- return;
- }
-
- /* If the structure doesn't take up a whole number of words, see
- whether the register value should be padded on the left or on
- the right. Set PADDING_CORRECTION to the number of padding
- bits needed on the left side.
-
- In most ABIs, the structure will be returned at the least end of
- the register, which translates to right padding on little-endian
- targets and left padding on big-endian targets. The opposite
- holds if the structure is returned at the most significant
- end of the register. */
- if (bytes % UNITS_PER_WORD != 0
- && (targetm.calls.return_in_msb (TREE_TYPE (retval_rhs))
- ? !BYTES_BIG_ENDIAN
- : BYTES_BIG_ENDIAN))
- padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
- * BITS_PER_UNIT));
-
- /* Copy the structure BITSIZE bits at a time. */
- for (bitpos = 0, xbitpos = padding_correction;
- bitpos < bytes * BITS_PER_UNIT;
- bitpos += bitsize, xbitpos += bitsize)
- {
- /* We need a new destination pseudo each time xbitpos is
- on a word boundary and when xbitpos == padding_correction
- (the first time through). */
- if (xbitpos % BITS_PER_WORD == 0
- || xbitpos == padding_correction)
- {
- /* Generate an appropriate register. */
- dst = gen_reg_rtx (word_mode);
- result_pseudos[xbitpos / BITS_PER_WORD] = dst;
-
- /* Clear the destination before we move anything into it. */
- emit_move_insn (dst, CONST0_RTX (GET_MODE (dst)));
- }
-
- /* We need a new source operand each time bitpos is on a word
- boundary. */
- if (bitpos % BITS_PER_WORD == 0)
- src = operand_subword_force (result_val,
- bitpos / BITS_PER_WORD,
- BLKmode);
-
- /* Use bitpos for the source extraction (left justified) and
- xbitpos for the destination store (right justified). */
- store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD,
- 0, 0, word_mode,
- extract_bit_field (src, bitsize,
- bitpos % BITS_PER_WORD, 1, false,
- NULL_RTX, word_mode, word_mode));
- }
-
- tmpmode = GET_MODE (result_rtl);
- if (tmpmode == BLKmode)
- {
- /* Find the smallest integer mode large enough to hold the
- entire structure and use that mode instead of BLKmode
- on the USE insn for the return register. */
- for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
- tmpmode != VOIDmode;
- tmpmode = GET_MODE_WIDER_MODE (tmpmode))
- /* Have we found a large enough mode? */
- if (GET_MODE_SIZE (tmpmode) >= bytes)
- break;
-
- /* A suitable mode should have been found. */
- gcc_assert (tmpmode != VOIDmode);
-
- PUT_MODE (result_rtl, tmpmode);
+ /* Use the mode of the result value on the return register. */
+ PUT_MODE (result_rtl, GET_MODE (val));
+ expand_value_return (val);
}
-
- if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode))
- result_reg_mode = word_mode;
else
- result_reg_mode = tmpmode;
- result_reg = gen_reg_rtx (result_reg_mode);
-
- for (i = 0; i < n_regs; i++)
- emit_move_insn (operand_subword (result_reg, i, 0, result_reg_mode),
- result_pseudos[i]);
-
- if (tmpmode != result_reg_mode)
- result_reg = gen_lowpart (tmpmode, result_reg);
-
- expand_value_return (result_reg);
+ expand_null_return ();
}
else if (retval_rhs != 0
&& !VOID_TYPE_P (TREE_TYPE (retval_rhs))
diff --git a/gcc/streamer-hooks.h b/gcc/streamer-hooks.h
index b4c65629e47..0c1d483ac6a 100644
--- a/gcc/streamer-hooks.h
+++ b/gcc/streamer-hooks.h
@@ -51,6 +51,16 @@ struct streamer_hooks {
and descriptors needed by the unpickling routines. It returns the
tree instantiated from the stream. */
tree (*read_tree) (struct lto_input_block *, struct data_in *);
+
+ /* [OPT] Called by lto_input_location to retrieve the source location of the
+ tree currently being read. If this hook returns NULL, lto_input_location
+ defaults to calling lto_input_location_bitpack. */
+ location_t (*input_location) (struct lto_input_block *, struct data_in *);
+
+ /* [OPT] Called by lto_output_location to write the source_location of the
+ tree currently being written. If this hook returns NULL,
+ lto_output_location defaults to calling lto_output_location_bitpack. */
+ void (*output_location) (struct output_block *, location_t);
};
#define stream_write_tree(OB, EXPR, REF_P) \
diff --git a/gcc/system.h b/gcc/system.h
index 340a560df2a..7c7d07ea3ee 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -797,7 +797,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
LABEL_ALIGN_MAX_SKIP LOOP_ALIGN_MAX_SKIP \
LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP JUMP_ALIGN_MAX_SKIP \
CAN_DEBUG_WITHOUT_FP UNLIKELY_EXECUTED_TEXT_SECTION_NAME \
- HOT_TEXT_SECTION_NAME LEGITIMATE_CONSTANT_P ALWAYS_STRIP_DOTDOT
+ HOT_TEXT_SECTION_NAME LEGITIMATE_CONSTANT_P ALWAYS_STRIP_DOTDOT \
+ OUTPUT_ADDR_CONST_EXTRA
/* Target macros only used for code built for the target, that have
moved to libgcc-tm.h or have never been present elsewhere. */
@@ -867,7 +868,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
FUNCTION_INCOMING_ARG IRA_COVER_CLASSES TARGET_VERSION \
MACHINE_TYPE TARGET_HAS_TARGETCM ASM_OUTPUT_BSS \
SETJMP_VIA_SAVE_AREA FORBIDDEN_INC_DEC_CLASSES \
- PREFERRED_OUTPUT_RELOAD_CLASS
+ PREFERRED_OUTPUT_RELOAD_CLASS SYSTEM_INCLUDE_DIR \
+ STANDARD_INCLUDE_DIR STANDARD_INCLUDE_COMPONENT
/* Hooks that are no longer used. */
#pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
@@ -881,6 +883,9 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
TARGET_HANDLE_OFAST TARGET_OPTION_OPTIMIZATION \
TARGET_IRA_COVER_CLASSES TARGET_HELP
+/* Arrays that were deleted in favor of a functional interface. */
+ #pragma GCC poison built_in_decls implicit_built_in_decls
+
/* Hooks into libgcc2. */
#pragma GCC poison LIBGCC2_DOUBLE_TYPE_SIZE LIBGCC2_WORDS_BIG_ENDIAN \
LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
diff --git a/gcc/target.def b/gcc/target.def
index 48a8e6d4a13..c3bec0e0391 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -456,7 +456,7 @@ DEFHOOK
(output_addr_const_extra,
"",
bool, (FILE *file, rtx x),
- default_asm_output_addr_const_extra)
+ hook_bool_FILEptr_rtx_false)
/* ??? The TARGET_PRINT_OPERAND* hooks are part of the asm_out struct,
even though that is not reflected in the macro name to override their
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 8ad517fd5ce..81fd12f7b78 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -371,21 +371,6 @@ default_mangle_assembler_name (const char *name ATTRIBUTE_UNUSED)
return get_identifier (stripped);
}
-/* The default implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
-
-bool
-default_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED,
- rtx x ATTRIBUTE_UNUSED)
-{
-#ifdef OUTPUT_ADDR_CONST_EXTRA
- OUTPUT_ADDR_CONST_EXTRA (file, x, fail);
- return true;
-
-fail:
-#endif
- return false;
-}
-
/* True if MODE is valid for the target. By "valid", we mean able to
be manipulated in non-trivial ways. In particular, this means all
the arithmetic is supported.
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 552407b21db..f19fb506bf5 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -67,8 +67,6 @@ extern void default_print_operand_address (FILE *, rtx);
extern bool default_print_operand_punct_valid_p (unsigned char);
extern tree default_mangle_assembler_name (const char *);
-extern bool default_asm_output_addr_const_extra (FILE *, rtx);
-
extern bool default_scalar_mode_supported_p (enum machine_mode);
extern bool targhook_words_big_endian (void);
extern bool targhook_float_words_big_endian (void);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 37a71e5e4d8..709fae4848c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,1045 @@
+2011-10-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/13657
+ * g++.dg/parse/error42.C: New.
+ * g++.old-deja/g++.other/ptrmem7.C: Tweak dg-errors.
+
+2011-10-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/50793
+ * g++.dg/init/value9.C: New.
+
+2011-10-19 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/torture/vshuf-32.inc: Add interleave permutations.
+ * gcc.dg/torture/vshuf-16.inc: Likewise.
+ * gcc.dg/torture/vshuf-8.inc: Likewise.
+ * gcc.dg/torture/vshuf-4.inc: Likewise.
+
+2011-10-19 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * gfortran.dg/sizeof_proc.f90: New.
+
+2011-10-19 Joseph Myers <joseph@codesourcery.com>
+
+ * g++.dg/compat/struct-layout-1_generate.c: Also pass -mno-mmx
+ -Wno-abi for i?86-*-mingw32* x86_64-*-mingw32* i?86-*-cygwin*.
+
+2011-10-19 Uros Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/50796
+ * gcc.dg/plugin/plugindir?.c Update dg_prune_output.
+
+2011-10-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/50787
+ * g++.dg/init/ref20.C: New.
+
+2011-10-19 Kai Tietz <ktietz@redhat.com>
+
+ PR middle-end/50795
+ * gcc.dg/tree-ssa/builtin-expect-1.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-2.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-3.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-4.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-5.c: Adjust test.
+
+2011-10-19 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50768
+ * gcc.dg/torture/pr50768.c: New testcase.
+
+2011-10-19 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/50340
+ * gcc.dg/pr50340.c: New.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ PR tree-optimization/50717
+
+ * gcc.dg/pr50717-1.c: New file.
+ * gcc.target/arm/wmul-12.c: Correct types.
+ * gcc.target/arm/wmul-8.c: Correct types.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50531
+ * g++.dg/cpp0x/defaulted32.C: New.
+
+ PR c++/50742
+ * g++.dg/lookup/using23.C: New.
+
+ PR c++/50500
+ * g++.dg/cpp0x/implicit12.C: New.
+ * g++.dg/cpp0x/defaulted20.C: Adjust.
+ * g++.dg/cpp0x/defaulted21.C: Adjust.
+ * g++.dg/cpp0x/implicit-copy.C: Adjust.
+ * g++.dg/cpp0x/implicit4.C: Adjust.
+ * g++.dg/cpp0x/implicit5.C: Adjust.
+ * g++.dg/cpp0x/implicit8.C: Adjust.
+ * g++.dg/cpp0x/lambda/lambda-ice2.C: Adjust.
+ * g++.dg/cpp0x/not_special.C: Adjust.
+ * g++.dg/cpp0x/rv-trivial-bug.C: Adjust.
+ * g++.dg/cpp0x/rv1n.C: Adjust.
+ * g++.dg/cpp0x/rv2n.C: Adjust.
+ * g++.dg/cpp0x/rv3n.C: Adjust.
+ * g++.dg/cpp0x/rv4n.C: Adjust.
+ * g++.dg/cpp0x/rv5n.C: Adjust.
+ * g++.dg/cpp0x/rv6n.C: Adjust.
+ * g++.dg/cpp0x/rv7n.C: Adjust.
+
+2011-10-18 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * gcc.target/i386/avx2-vpop-check.h: New header.
+ * gcc.target/i386/avx2-vpaddd-3.c: New test.
+ * gcc.target/i386/avx2-vpaddw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpaddb-3.c: Ditto.
+ * gcc.target/i386/avx2-vpaddq-3.c: Ditto.
+ * gcc.target/i386/avx2-vpand-3.c: Ditto.
+ * gcc.target/i386/avx2-vpmulld-3.c: Ditto.
+ * gcc.target/i386/avx2-vpmullw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsrad-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsraw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsrld-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsrlw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubb-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubd-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubq-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubw-3.c: Ditto.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * gfortran.dg/coarray_subobject_1.f90: New test.
+ * gfortran.dg/coarray/subobject_1.f90: New test.
+
+2011-10-18 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/50205
+ * gcc.dg/pr50205.c: New.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50767
+ * gcc.dg/torture/pr50767.c: New testcase.
+
+2011-10-18 Julian Brown <julian@codesourcery.com>
+
+ * lib/target-supports.exp (check_effective_target_arm_unaligned): New.
+ * gcc.target/arm/unaligned-memcpy-1.c: New.
+ * gcc.target/arm/unaligned-memcpy-2.c: New.
+ * gcc.target/arm/unaligned-memcpy-3.c: New.
+ * gcc.target/arm/unaligned-memcpy-4.c: New.
+
+2011-10-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * gfortran.dg/iso_c_binding_class.f03: New.
+
+2011-10-18 Ira Rosen <ira.rosen@linaro.org>
+
+ * testsuite/lib/target-supports.exp
+ (check_effective_target_vect_widen_shift): New.
+ * gcc.dg/vect/vect-widen-shift-s16.c: New.
+ * gcc.dg/vect/vect-widen-shift-s8.c: New.
+ * gcc.dg/vect/vect-widen-shift-u16.c: New.
+ * gcc.dg/vect/vect-widen-shift-u8.c: New.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/torture/restrict-1.c: New testcase.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * g++.dg/ext/bases.C: New test.
+
+2011-10-17 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/fand.c: Remove __LP64__ ifdefs and expect
+ all operations to emit VIS instructions.
+ * gcc.target/sparc/fandnot.c: Likewise.
+ * gcc.target/sparc/fnot.c: Likewise.
+ * gcc.target/sparc/for.c: Likewise.
+ * gcc.target/sparc/fornot.c: Likewise.
+ * gcc.target/sparc/fxnor.c: Likewise.
+ * gcc.target/sparc/fxor.c: Likewise.
+ * gcc.target/sparc/combined-1.c: Revert change to use -O2, no longer
+ needed.
+
+2011-10-17 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.c-torture/execute/vshuf-v16hi.c: New test.
+ * gcc.dg/torture/vshuf-16.inc: New file.
+ * gcc.dg/torture/vshuf-2.inc: New file.
+ * gcc.dg/torture/vshuf-32.inc: New file.
+ * gcc.dg/torture/vshuf-4.inc: New file.
+ * gcc.dg/torture/vshuf-8.inc: New file.
+ * gcc.dg/torture/vshuf-main.inc: New file.
+ * gcc.dg/torture/vshuf-v16hi.c: New test.
+ * gcc.dg/torture/vshuf-v16qi.c: New test.
+ * gcc.dg/torture/vshuf-v2df.c: New test.
+ * gcc.dg/torture/vshuf-v2di.c: New test.
+ * gcc.dg/torture/vshuf-v2sf.c: New test.
+ * gcc.dg/torture/vshuf-v2si.c: New test.
+ * gcc.dg/torture/vshuf-v32qi.c: New test.
+ * gcc.dg/torture/vshuf-v4df.c: New test.
+ * gcc.dg/torture/vshuf-v4di.c: New test.
+ * gcc.dg/torture/vshuf-v4hi.c: New test.
+ * gcc.dg/torture/vshuf-v4sf.c: New test.
+ * gcc.dg/torture/vshuf-v4si.c: New test.
+ * gcc.dg/torture/vshuf-v8hi.c: New test.
+ * gcc.dg/torture/vshuf-v8qi.c: New test.
+ * gcc.dg/torture/vshuf-v8sf.c: New test.
+ * gcc.dg/torture/vshuf-v8si.c: New test.
+
+2011-10-17 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50746
+ * gcc.dg/vect/vect-114.c: Remove vect_hw_misalign.
+
+2011-10-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/50736
+ * g++.dg/cpp0x/lambda/lambda-capture-neg.C: New.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44524
+ * g++.dg/parse/error41.C: New.
+ * g++.dg/parse/error20.C: Adjust.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50757
+ * g++.dg/warn/format7.C: New.
+ * obj-c++.dg/warn7.mm: Likewise.
+
+2011-10-17 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50729
+ * gcc.dg/torture/pr50729.c: New testcase.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * lib/prune.exp (prune_gcc_output): Prune output referring to
+ included files.
+ * gcc.dg/cpp/macro-exp-tracking-1.c: New test.
+ * gcc.dg/cpp/macro-exp-tracking-2.c: Likewise.
+ * gcc.dg/cpp/macro-exp-tracking-3.c: Likewise.
+ * gcc.dg/cpp/pragma-diagnostic-2.c: Likewise.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc.dg/cpp/pragma-diagnostic-1.c: New test.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/48489
+ * g++.dg/inherit/error5.C: New.
+
+2011-10-17 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ PR fortran/50752
+ * gfortran.dg/kind_tests_4.f90: New.
+
+2011-10-17 Ira Rosen <ira.rosen@linaro.org>
+
+ * gcc.dg/vect/vect-21.c: Expect the loops to get vectorized on
+ targets that support vector condition.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * gfortran.dg/c_kind_tests_3.f03: New.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50547
+ * gfortran.dg/elemental_args_check_4.f90: New.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50727
+ * gcc.dg/vect/pr50727.c: New test.
+
+2011-10-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/vla-23.c: New test.
+
+2011-10-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * gcc.dg/vect/vect-cond-9.c: New test.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ * gcc.dg/vect/bb-slp-29.c: New test.
+
+2011-10-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50732
+ * g++.dg/ext/is_base_of_incomplete.C: New.
+ * g++.dg/ext/is_base_of_diagnostic.C: Adjust dg-errors.
+ * g++.dg/ext/unary_trait_incomplete.C: Likewise.
+
+2011-10-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/sparc/combined-1.c: Compile at -O2.
+
+2011-10-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/fma_float_?.c (dg-prune_output): Remove.
+ (dg-options): Add -Wno-attributes.
+ * gcc.target/i386/fma_double_?.c: Ditto.
+ * gcc.target/i386/fma_run_float_?.c: Ditto.
+ * gcc.target/i386/fma_run_double_?.c: Ditto.
+ * gcc.target/i386/l_fma_float_?.c: Dtto.
+ * gcc.target/i386/l_fma_double_?.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_?.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_?.c: Ditto.
+
+2011-10-15 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/bind_c_usage_23.f90: Change TR 29113 to TS 29113 in
+ the comments.
+ * gfortran.dg/bind_c_usage_24.f90: Ditto.
+ * gfortran.dg/rank_3.f90: Ditto.
+ * gfortran.dg/bind_c_usage_22.f90: Ditto, change -std=f2008tr to
+ -std=f2008ts in dg-options.
+ * gfortran.dg/rank_4.f90: Ditto.
+
+2011-10-15 Oleg Endo <oleg.endo@t-online.de>
+
+ PR target/49263
+ * gcc.target/sh/pr49263.c: New.
+
+2011-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/debug1.ads: Tweak.
+
+2011-10-14 Kai Tietz <ktietz@redhat.com>
+
+ * gfortran.fortran-torture/compile/logical-2.f90: New test.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/sse2-mul-1.c: New test.
+ * gcc.target/i386/sse4_1-mul-1.c: New test.
+ * gcc.target/i386/avx-mul-1.c: New test.
+ * gcc.target/i386/xop-mul-1.c: New test.
+ * gcc.target/i386/avx2-mul-1.c: New test.
+
+2011-10-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/50563
+ * g++.dg/cpp0x/nsdmi-list1.C: New.
+
+ PR c++/50707
+ * g++.dg/cpp0x/nsdmi-const1.C: New.
+
+2011-10-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50570
+ * gfortran.dg/pointer_intent_5.f90: New.
+
+2011-10-14 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
+
+ * gcc.target/i386/warn-vect-op-3.c: Exclude 32-bit architectures.
+ * gcc.target/i386/warn-vect-op-1.c: Ditto.
+ * gcc.target/i386/warn-vect-op-2.c: Ditto.
+
+2011-10-14 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50718
+ * gfortran.dg/pointer_check_11.f90: New.
+ * gfortran.dg/pointer_check_12.f90: New.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38174
+ * g++.dg/overload/operator4.C: New.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * gcc.dg/di-longlong64-sync-1.c: New test.
+ * gcc.dg/di-sync-multithread.c: New test.
+ * gcc.target/arm/di-longlong64-sync-withhelpers.c: New test.
+ * gcc.target/arm/di-longlong64-sync-withldrexd.c: New test.
+ * lib/target-supports.exp: (arm_arch_*_ok): Series of effective-target
+ tests for v5, v6, v6k, and v7-a, and add-options helpers.
+ (check_effective_target_arm_arm_ok): New helper.
+ (check_effective_target_sync_longlong): New helper.
+
+2011-10-14 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50723
+ * gcc.dg/torture/pr50723.c: New testcase.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/17212
+ * g++.dg/warn/format6.C: New.
+ * obj-c++.dg/warn6.mm: Likewise.
+
+2011-10-13 Richard Henderson <rth@redhat.com>
+
+ * lib/target-supports.exp (check_effective_target_vect_shift_scalar):
+ Delete.
+ * gcc.dg/vect/vec-scal-opt.c: Don't test vect_shift_scalar.
+ * gcc.dg/vect/vec-scal-opt1.c: Likewise.
+ * gcc.dg/vect/vec-scal-opt2.c: Likewise.
+
+2011-10-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/50614
+ * g++.dg/cpp0x/nsdmi-template2.C: New.
+
+ PR c++/50437
+ * g++.dg/cpp0x/lambda/lambda-auto1.C: New.
+
+ PR c++/50618
+ * g++.dg/init/vbase1.C: New.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/sse4_1-phminposuw-2.c: New test.
+ * gcc.target/i386/sse4_1-phminposuw-3.c: New test.
+ * gcc.target/i386/avx-vphminposuw-2.c: New test.
+ * gcc.target/i386/avx-vphminposuw-3.c: New test.
+
+2011-10-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/pr50712.c: Check ia32 instead of ilp32.
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/builtins-67.c: Guard iround and irint with HAVE_C99_RUNTIME.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50712
+ * gcc.target/i386/pr50712.c: New testcase.
+
+2011-10-13 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.dg/memcpy-4.c: New test.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50698
+ * g++.dg/vect/pr50698.cc: New testcase.
+
+2011-10-12 Janis Johnson <janisjo@codesourcery.com>
+
+ * gcc.target/powerpc/warn-1.c: Skip if not powerpc_vsx_ok.
+ * gcc.target/powerpc/warn-2.c: Ditto.
+
+ * gcc.target/powerpc/ppc-fma-3.c: Require powerpc_fprs.
+ * gcc.target/powerpc/ppc-fma-4.c: Likewise.
+ * gcc.target/powerpc/ppc-fma-5.c: Likewise.
+ * gcc.target/powerpc/ppc-fma-7.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-11.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-3.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-7.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-8.c: Likewise.
+ * gcc.target/powerpc/ppc-pow.c: Likewise.
+ * gcc.target/powerpc/recip-1.c: Likewise.
+ * gcc.target/powerpc/recip-2.c: Likewise.
+ * gcc.target/powerpc/recip-3.c: Likewise.
+ * gcc.target/powerpc/recip-4.c: Likewise.
+ * gcc.target/powerpc/recip-5.c: Likewise.
+
+2011-10-12 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/cmask.c: Remove 'vis3' target check and specify
+ '-mvis3' instead of 'mcpu=niagara3' in options.
+ * gcc.target/sparc/fhalve.c: Likewise.
+ * gcc.target/sparc/fnegop.c: Likewise.
+ * gcc.target/sparc/fpadds.c: Likewise.
+ * gcc.target/sparc/fshift.c: Likewise.
+ * gcc.target/sparc/fucmp.c: Likewise.
+ * gcc.target/sparc/lzd.c: Likewise.
+ * gcc.target/sparc/vis3misc.c: Likewise.
+ * gcc.target/sparc/xmul.c: Likewise.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/vect1.ad[sb]: New test.
+ * gnat.dg/vect1_pkg.ads: New helper.
+ * gnat.dg/vect2.ad[sb]: New test.
+ * gnat.dg/vect2_pkg.ads: New helper.
+ * gnat.dg/vect3.ad[sb]: New test.
+ * gnat.dg/vect3_pkg.ads: New helper.
+ * gnat.dg/vect4.ad[sb]: New test.
+ * gnat.dg/vect4_pkg.ads: New helper.
+ * gnat.dg/vect5.ad[sb]: New test.
+ * gnat.dg/vect5_pkg.ads: New helper.
+ * gnat.dg/vect6.ad[sb]: New test.
+ * gnat.dg/vect6_pkg.ads: New helper.
+
+2011-10-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/fma_run_double_1.c: Add -mfpmath=sse.
+ * gcc.target/i386/fma_run_double_2.c: Likewise.
+ * gcc.target/i386/fma_run_double_3.c: Likewise.
+ * gcc.target/i386/fma_run_double_4.c: Likewise.
+ * gcc.target/i386/fma_run_double_5.c: Likewise.
+ * gcc.target/i386/fma_run_double_6.c: Likewise.
+ * gcc.target/i386/fma_run_float_1.c: Likewise.
+ * gcc.target/i386/fma_run_float_2.c: Likewise.
+ * gcc.target/i386/fma_run_float_3.c: Likewise.
+ * gcc.target/i386/fma_run_float_4.c: Likewise.
+ * gcc.target/i386/fma_run_float_5.c: Likewise.
+ * gcc.target/i386/fma_run_float_6.c: Likewise.
+
+ * gcc.target/i386/l_fma_double_1.c: Add -mtune=generic and
+ remove the extra dg-options.
+ * gcc.target/i386/l_fma_double_2.c: Likewise.
+ * gcc.target/i386/l_fma_double_3.c: Likewise.
+ * gcc.target/i386/l_fma_double_4.c: Likewise.
+ * gcc.target/i386/l_fma_double_5.c: Likewise.
+ * gcc.target/i386/l_fma_double_6.c: Likewise.
+ * gcc.target/i386/l_fma_float_1.c: Likewise.
+ * gcc.target/i386/l_fma_float_2.c: Likewise.
+ * gcc.target/i386/l_fma_float_3.c: Likewise.
+ * gcc.target/i386/l_fma_float_4.c: Likewise.
+ * gcc.target/i386/l_fma_float_5.c: Likewise.
+ * gcc.target/i386/l_fma_float_6.c: Likewise.
+
+2011-10-12 Paul Koning <pkoning@gcc.gnu.org>
+
+ PR tree-optimization/50189
+ * g++.dg/torture/pr50189.C: New testcase.
+
+2011-10-12 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50700
+ * gcc.dg/builtin-object-size-12.c: New testcase.
+
+2011-10-12 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/50565
+ * gcc.c-torture/compile/pr50565-1.c,
+ gcc.c-torture/compile/pr50565-2.c: New tests.
+
+2011-10-11 Jason Merrill <jason@redhat.com>
+
+ PR c++/49855
+ PR c++/49896
+ * g++.dg/template/constant1.C: New.
+ * g++.dg/template/constant2.C: New.
+ * g++.dg/cpp0x/constexpr-template3.C: New.
+
+2011-10-11 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
+
+ * gcc.target/i386/warn-vect-op-3.c: New test.
+ * gcc.target/i386/warn-vect-op-1.c: New test.
+ * gcc.target/i386/warn-vect-op-2.c: New test.
+
+2011-10-11 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.dg/pr49994-3.c: Add -mbackchain for s390 and s390x.
+
+2011-10-11 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50204
+ * gcc.dg/tree-ssa/ssa-fre-36.c: New testcase.
+
+2011-10-11 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/20090223-1.c: Add -Wno-attributes.
+
+2011-10-11 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * gcc.target/i386/fma_double_1.c: Add -mfpmath=sse.
+ * gcc.target/i386/fma_double_2.c: Ditto.
+ * gcc.target/i386/fma_double_3.c: Ditto.
+ * gcc.target/i386/fma_double_4.c: Ditto.
+ * gcc.target/i386/fma_double_5.c: Ditto.
+ * gcc.target/i386/fma_double_6.c: Ditto.
+ * gcc.target/i386/fma_float_1.c: Ditto.
+ * gcc.target/i386/fma_float_2.c: Ditto.
+ * gcc.target/i386/fma_float_3.c: Ditto.
+ * gcc.target/i386/fma_float_4.c: Ditto.
+ * gcc.target/i386/fma_float_5.c: Ditto.
+ * gcc.target/i386/fma_float_6.c: Ditto.
+ * gcc.target/i386/l_fma_double_1.c: Ditto.
+ * gcc.target/i386/l_fma_double_2.c: Ditto.
+ * gcc.target/i386/l_fma_double_3.c: Ditto.
+ * gcc.target/i386/l_fma_double_4.c: Ditto.
+ * gcc.target/i386/l_fma_double_5.c: Ditto.
+ * gcc.target/i386/l_fma_double_6.c: Ditto.
+ * gcc.target/i386/l_fma_float_1.c: Ditto.
+ * gcc.target/i386/l_fma_float_2.c: Ditto.
+ * gcc.target/i386/l_fma_float_3.c: Ditto.
+ * gcc.target/i386/l_fma_float_4.c: Ditto.
+ * gcc.target/i386/l_fma_float_5.c: Ditto.
+ * gcc.target/i386/l_fma_float_6.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_1.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_2.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_3.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_4.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_5.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_6.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_1.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_2.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_3.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_4.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_5.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_6.c: Ditto.
+
+2011-10-11 Tristan Gingold <gingold@adacore.com>
+
+ * gcc.dg/va-arg-4.c: New test.
+ * gcc.dg/va-arg-5.c: Ditto.
+
+2011-10-11 Uros Bizjak <ubizjak@gmail.com>
+
+ * lib/target-supports.exp (check_effective_target_fd_truncate):
+ Close and unlink test file before exit.
+
+2011-10-10 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/50564
+ * gfortran.dg/forall_15.f90: New test case.
+
+2011-10-10 Aldy Hernandez <aldyh@redhat.com>
+ Andrew Macleod <amacleod@redhat.com>
+
+ * gcc.dg/simulate-thread/simulate-thread.gdb: Call
+ wrappers for *other_threads() and *final_verify().
+ * gcc.dg/simulate-thread/simulate-thread.h
+ (simulate_thread_wrapper_other_threads): New.
+ (simulate_thread_wrapper_final_verify): New.
+
+2011-10-10 Uros Bizjak <ubizjak@gmail.com>
+
+ * lib/gcc-gdb-test.exp (gdb-test): Delete $cmd_file before return.
+
+2011-10-10 Janis Johnson <janisjo@codesourcery.com>
+
+ * gcc.dg/graphite/id-pr46845.c: Include powerpc for warning options.
+
+2011-10-10 Kirill Yukhin <kirill.yukhin@intel.com>
+ Yakovlev Vladimir <vladimir.b.yakovlev@intel.com>
+
+ * gcc.target/i386/fma_1.h: New file.
+ * gcc.target/i386/fma_2.h: Likewise.
+ * gcc.target/i386/fma_3.h: Likewise.
+ * gcc.target/i386/fma_4.h: Likewise.
+ * gcc.target/i386/fma_5.h: Likewise.
+ * gcc.target/i386/fma_6.h: Likewise.
+ * gcc.target/i386/fma_double_1.c: Likewise.
+ * gcc.target/i386/fma_double_2.c: Likewise.
+ * gcc.target/i386/fma_double_3.c: Likewise.
+ * gcc.target/i386/fma_double_4.c: Likewise.
+ * gcc.target/i386/fma_double_5.c: Likewise.
+ * gcc.target/i386/fma_double_6.c: Likewise.
+ * gcc.target/i386/fma_float_1.c: Likewise.
+ * gcc.target/i386/fma_float_2.c: Likewise.
+ * gcc.target/i386/fma_float_3.c: Likewise.
+ * gcc.target/i386/fma_float_4.c: Likewise.
+ * gcc.target/i386/fma_float_5.c: Likewise.
+ * gcc.target/i386/fma_float_6.c: Likewise.
+ * gcc.target/i386/fma_main.h: Likewise.
+ * gcc.target/i386/fma_run_double_1.c: Likewise.
+ * gcc.target/i386/fma_run_double_2.c: Likewise.
+ * gcc.target/i386/fma_run_double_3.c: Likewise.
+ * gcc.target/i386/fma_run_double_4.c: Likewise.
+ * gcc.target/i386/fma_run_double_5.c: Likewise.
+ * gcc.target/i386/fma_run_double_6.c: Likewise.
+ * gcc.target/i386/fma_run_double_results_1.h: Likewise.
+ * gcc.target/i386/fma_run_double_results_2.h: Likewise.
+ * gcc.target/i386/fma_run_double_results_3.h: Likewise.
+ * gcc.target/i386/fma_run_double_results_4.h: Likewise.
+ * gcc.target/i386/fma_run_double_results_5.h: Likewise.
+ * gcc.target/i386/fma_run_double_results_6.h: Likewise.
+ * gcc.target/i386/fma_run_float_1.c: Likewise.
+ * gcc.target/i386/fma_run_float_2.c: Likewise.
+ * gcc.target/i386/fma_run_float_3.c: Likewise.
+ * gcc.target/i386/fma_run_float_4.c: Likewise.
+ * gcc.target/i386/fma_run_float_5.c: Likewise.
+ * gcc.target/i386/fma_run_float_6.c: Likewise.
+ * gcc.target/i386/fma_run_float_results_1.h: Likewise.
+ * gcc.target/i386/fma_run_float_results_2.h: Likewise.
+ * gcc.target/i386/fma_run_float_results_3.h: Likewise.
+ * gcc.target/i386/fma_run_float_results_4.h: Likewise.
+ * gcc.target/i386/fma_run_float_results_5.h: Likewise.
+ * gcc.target/i386/fma_run_float_results_6.h: Likewise.
+ * gcc.target/i386/l_fma_1.h: Likewise.
+ * gcc.target/i386/l_fma_2.h: Likewise.
+ * gcc.target/i386/l_fma_3.h: Likewise.
+ * gcc.target/i386/l_fma_4.h: Likewise.
+ * gcc.target/i386/l_fma_5.h: Likewise.
+ * gcc.target/i386/l_fma_6.h: Likewise.
+ * gcc.target/i386/l_fma_double_1.c: Likewise.
+ * gcc.target/i386/l_fma_double_2.c: Likewise.
+ * gcc.target/i386/l_fma_double_3.c: Likewise.
+ * gcc.target/i386/l_fma_double_4.c: Likewise.
+ * gcc.target/i386/l_fma_double_5.c: Likewise.
+ * gcc.target/i386/l_fma_double_6.c: Likewise.
+ * gcc.target/i386/l_fma_float_1.c: Likewise.
+ * gcc.target/i386/l_fma_float_2.c: Likewise.
+ * gcc.target/i386/l_fma_float_3.c: Likewise.
+ * gcc.target/i386/l_fma_float_4.c: Likewise.
+ * gcc.target/i386/l_fma_float_5.c: Likewise.
+ * gcc.target/i386/l_fma_float_6.c: Likewise.
+ * gcc.target/i386/l_fma_main.h: Likewise.
+ * gcc.target/i386/l_fma_run_double_1.c: Likewise.
+ * gcc.target/i386/l_fma_run_double_2.c: Likewise.
+ * gcc.target/i386/l_fma_run_double_3.c: Likewise.
+ * gcc.target/i386/l_fma_run_double_4.c: Likewise.
+ * gcc.target/i386/l_fma_run_double_5.c: Likewise.
+ * gcc.target/i386/l_fma_run_double_6.c: Likewise.
+ * gcc.target/i386/l_fma_run_float_1.c: Likewise.
+ * gcc.target/i386/l_fma_run_float_2.c: Likewise.
+ * gcc.target/i386/l_fma_run_float_3.c: Likewise.
+ * gcc.target/i386/l_fma_run_float_4.c: Likewise.
+ * gcc.target/i386/l_fma_run_float_5.c: Likewise.
+ * gcc.target/i386/l_fma_run_float_6.c: Likewise.
+
+2011-10-10 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50389
+ * gcc.dg/torture/pr50389.c: New testcase.
+
+2011-10-10 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50195
+ * gcc.dg/builtins-47.c: Optimize.
+
+2011-10-10 Aldy Hernandez <aldyh@redhat.com>
+
+ * lib/gcc-simulate-thread.exp: New.
+ * gcc.dg/simulate-thread/guality.h: New.
+ * gcc.dg/simulate-thread/simulate-thread.h: New.
+ * gcc.dg/simulate-thread/simulate-thread.exp: New.
+ * gcc.dg/simulate-thread/simulate-thread.gdb: New.
+ * gcc.dg/simulate-thread/README: New.
+ * g++.dg/simulate-thread/guality.h: New.
+ * g++.dg/simulate-thread/simulate-thread.h: New.
+ * g++.dg/simulate-thread/simulate-thread.exp: New.
+ * g++.dg/simulate-thread/simulate-thread.gdb: New.
+ * c-c++-common/cxxbitfields-2.c: Remove.
+ * c-c++-common/cxxbitfields.c: Remove.
+ * c-c++-common/cxxbitfields-4.c: Remove.
+ * c-c++-common/cxxbitfields-5.c: Remove.
+ * c-c++-common/simulate-thread/bitfields-1.c: New.
+ * c-c++-common/simulate-thread/bitfields-2.c: New.
+ * c-c++-common/simulate-thread/bitfields-3.c: New.
+ * c-c++-common/simulate-thread/bitfields-4.c: New.
+
+2011-10-09 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38980
+ * g++.dg/warn/format5.C: New.
+
+2011-10-09 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50273
+ * gfortran.dg/common_14.f90: Compile with -Wno-align-commons.
+ * gfortran.dg/common_16.f90: New.
+
+2011-10-09 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/iso_c_binding_param_1.f90: New.
+ * gfortran.dg/iso_c_binding_param_2.f90: New.
+ * gfortran.dg/c_sizeof_2.f90: Update dg-error.
+
+2011-10-09 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50635
+ * gcc.dg/vect/pr50635.c: New test.
+
+2011-10-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50659
+ * gfortran.dg/proc_decl_27.f90: New.
+
+2011-10-08 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ PR libobjc/50428
+ * objc/execute/initialize-1.m: New test.
+
+2011-10-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/47844
+ * gfortran.dg/pointer_function_result_1.f90 : New test.
+
+2011-10-07 David S. Miller <davem@davemloft.net>
+
+ PR 50655
+ * gcc.target/sparc/sparc.exp: Add vis3 target test.
+ * gcc.target/sparc/cmask.c: Use it.
+ * gcc.target/sparc/fhalve.c: Likewise.
+ * gcc.target/sparc/fnegop.c: Likewise.
+ * gcc.target/sparc/fpadds.c: Likewise.
+ * gcc.target/sparc/fshift.c: Likewise.
+ * gcc.target/sparc/fucmp.c: Likewise.
+ * gcc.target/sparc/lzd.c: Likewise.
+ * gcc.target/sparc/vis3misc.c: Likewise.
+ * gcc.target/sparc/xmul.c: Likewise.
+
+2011-10-07 Richard Henderson <rth@redhat.com>
+
+ * gcc.target/i386/avx256-unaligned-load-2.c: Tweek vinsert pattern
+ match for avx2.
+ * gcc.target/i386/avx256-unaligned-store-2.c: Similarly.
+
+2011-10-07 Andrew Stubbs <ams@codesourcery.com>
+
+ * gcc.dg/pr50193-1.c: New file.
+ * gcc.target/arm/shiftable.c: New file.
+
+2011-10-07 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50625
+ * gfortran.dg/class_46.f03: New.
+
+2011-10-06 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * gcc.dg/pr47276.c (ASMNAME, ASMNAME2, STRING): Define.
+ (__EI___vsyslog_chk, __EI_syslog, __EI_vsyslog): Use ASMNAME.
+ (syslog, vsyslog, __vsyslog_chk): Likewise.
+
+ * gcc.dg/lto/20081222_1.c (ASMNAME, ASMNAME2, STRING): Define.
+ (x, EXT_x): Use ASMNAME.
+
+ * gcc.dg/torture/pr48044.c (ASMNAME, ASMNAME2, STRING): Define.
+ (a, c): Use ASMNAME.
+
+2011-10-07 Tom de Vries <tom@codesourcery.com>
+
+ PR middle-end/50527
+ * gcc.dg/pr50527.c: New test.
+
+2011-10-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50650
+ * gcc.c-torture/compile/pr50650.c: New test.
+
+2011-10-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR tree-optimization/50575
+ * gcc.c-torture/execute/vector-compare-2.x: New file.
+
+2011-10-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR middle-end/50125
+ * gcc.dg/uninit-B.c (baz): Remove xfail *-*-*.
+ * gcc.dg/uninit-pr19430.c (main): Remove xfail *-*-*.
+ (bar3): Likewise.
+
+2011-10-07 Richard Guenther <rguenther@suse.de>
+
+ PR testsuite/50637
+ * gcc.dg/vect/vect-align-2.c: Increase array size.
+
+2011-10-07 Uros Bizjak <ubizjak@gmail.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/50603
+ * gcc.target/i386/pr50603.c: New test.
+
+2011-10-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/39164
+ * g++.dg/cpp0x/default31.C: New.
+
+2011-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * lib/target-supports.exp (check_effective_target_vect_cond_mixed):
+ New.
+ * gcc.dg/vect/vect-cond-8.c: New test.
+
+2011-10-06 Richard Henderson <rth@redhat.com>
+
+ * gcc.c-torture/execute/vect-shuffle-1.c: Remove.
+ * gcc.c-torture/execute/vect-shuffle-2.c: Remove.
+ * gcc.c-torture/execute/vect-shuffle-3.c: Remove.
+ * gcc.c-torture/execute/vect-shuffle-4.c: Remove.
+ * gcc.c-torture/execute/vect-shuffle-5.c: Remove.
+ * gcc.c-torture/execute/vect-shuffle-6.c: Remove.
+ * gcc.c-torture/execute/vect-shuffle-7.c: Remove.
+ * gcc.c-torture/execute/vect-shuffle-8.c: Remove.
+ * gcc.c-torture/execute/vshuf-16.inc: New file.
+ * gcc.c-torture/execute/vshuf-2.inc: New file.
+ * gcc.c-torture/execute/vshuf-4.inc: New file.
+ * gcc.c-torture/execute/vshuf-8.inc: New file.
+ * gcc.c-torture/execute/vshuf-main.inc: New file.
+ * gcc.c-torture/execute/vshuf-v16qi.c: New test.
+ * gcc.c-torture/execute/vshuf-v2df.c: New test.
+ * gcc.c-torture/execute/vshuf-v2di.c: New test.
+ * gcc.c-torture/execute/vshuf-v2sf.c: New test.
+ * gcc.c-torture/execute/vshuf-v2si.c: New test.
+ * gcc.c-torture/execute/vshuf-v4df.c: New test.
+ * gcc.c-torture/execute/vshuf-v4di.c: New test.
+ * gcc.c-torture/execute/vshuf-v4hi.c: New test.
+ * gcc.c-torture/execute/vshuf-v4sf.c: New test.
+ * gcc.c-torture/execute/vshuf-v4si.c: New test.
+ * gcc.c-torture/execute/vshuf-v8hi.c: New test.
+ * gcc.c-torture/execute/vshuf-v8qi.c: New test.
+ * gcc.c-torture/execute/vshuf-v8si.c: New test.
+
+2011-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/49279
+ * gcc.dg/tree-ssa/restrict-4.c: XFAIL.
+ * gcc.c-torture/execute/pr49279.c: New test.
+
+2011-10-06 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR target/49049
+ * gcc.c-torture/compile/pr49049.c: New test.
+
+2011-10-06 Ulrich Weigand <ulrich.weigand@linaro.org>
+
+ PR target/50305
+ * gcc.target/arm/pr50305.c: New test.
+
+2011-10-06 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/38884
+ * gcc.dg/tree-ssa/ssa-fre-34.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-fre-35.c: Likewise.
+
+2011-10-05 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/lzd.c: New test.
+ * gcc.target/sparc/popc.c: New test.
+
+2011-10-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/strlenopt-21.c (dg-options): Remove -fdump-tree-optimized.
+ * gcc.dg/ipa/inline-5.c: Cleanup inline ipa dump.
+ * g++.dg/other/final1.C: Cleanup original tree dump.
+
+2011-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50613
+ * gcc.dg/pr50613.c: New test.
+
+2011-10-05 Richard Henderson <rth@redhat.com>
+
+ * gcc.c-torture/execute/vect-shuffle-1.c: Rewrite.
+ * gcc.c-torture/execute/vect-shuffle-2.c: Rewrite.
+ * gcc.c-torture/execute/vect-shuffle-3.c: Rewrite.
+ * gcc.c-torture/execute/vect-shuffle-4.c: Rewrite.
+ * gcc.c-torture/execute/vect-shuffle-5.c: Rewrite.
+ * gcc.c-torture/execute/vect-shuffle-6.c: New test.
+ * gcc.c-torture/execute/vect-shuffle-7.c: New test.
+ * gcc.c-torture/execute/vect-shuffle-8.c: New test.
+
+2011-10-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/vect/vect.exp (VEC_CFLAGS): Move initialization after
+ DEFAULT_VECTFLAGS initialization. Append "-fdump-tree-veclower2".
+ * gcc.dg/vect/vec-scal-opt.c: Scan and cleanup veclower2 tree dump.
+ * gcc.dg/vect/vec-scal-opt1.c: Ditto.
+ * gcc.dg/vect/vec-scal-opt2.c: Ditto.
+
+2011-10-05 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/38885
+ * gcc.dg/tree-ssa/ssa-fre-33.c: New testcase.
+
+2011-10-05 Bernd Schmidt <bernds@codesourcery.com>
+
+ * gcc.target/i386/sw-1.c: New test.
+
+2011-10-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/avx256-unaligned-load-3.c (dg-options): Add
+ -mtune=generic.
+ * gcc.target/i386/avx256-unaligned-store-3.c (dg-options): Ditto.
+
+2011-10-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/torture/builtin-complex-1.c: Use dg-add-options ieee.
+
+2011-10-04 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/fhalve.c: New test.
+ * gcc.target/sparc/fnegop.c: New test.
+ * gcc.target/sparc/xmul.c: New test.
+
+2011-10-04 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/35831
+ * gfortran.dg/dummy_procedure_6.f90: New.
+
+2011-10-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50604
+ * gcc.dg/pr50604.c: New test.
+
+2011-10-04 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR tree-optimization/49662
+ * gcc.dg/graphite/interchange-14.c: Remove xfail *-*-*.
+ * gcc.dg/graphite/interchange-15.c: Likewise.
+ * gcc.dg/graphite/interchange-mvt.c: Likewise.
+
+2011-10-04 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/tree-ssa/restrict-4.c: New test.
+
+2011-10-04 Artem Shinkarov <artyom.shinkaroff@gmail.com>
+
+ * gcc.c-torture/execute/vector-compare-1.c: Fix trailing white spaces.
+ (main): Use __typeof to get result type of comparison.
+
+2011-10-04 Ira Rosen <ira.rosen@linaro.org>
+
+ * lib/target-supports.exp (check_effective_target_vect_multiple_sizes):
+ Make et_vect_multiple_sizes_saved global.
+ (check_effective_target_vect64): Make et_vect64_saved global.
+
+2011-10-03 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
+
+ * gcc.c-torture/execute/vect-shuffle-2.c: New test.
+ * gcc.c-torture/execute/vect-shuffle-4.c: New test.
+ * gcc.c-torture/execute/vect-shuffle-1.c: New test.
+ * gcc.dg/builtin-complex-err-1.c: Adjust.
+
+2011-10-02 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/range-for22.C: New.
+
+ * g++.dg/cpp0x/variadic65.C: Remove xfails.
+ * g++.dg/cpp0x/variadic82.C: Remove xfails.
+ * g++.dg/cpp0x/variadic83.C: Remove xfails.
+ * g++.dg/cpp0x/variadic105.C: Remove xfails.
+
+ * g++.dg/cpp0x/nsdmi5.C: New.
+
+2011-10-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR target/50579
+ * gcc.target/mips/mips.exp (mips_long32_abi_p, mips_long64_abi_p):
+ New procedures.
+ (mips-dg-options): Force an ABI option if the current ABI is
+ incompatible with the required -mlong setting. Likewise force
+ a long setting if the current one is incompatible with the
+ chosen ABI. Keep abi_test_option_p, abi and eabi_p updated
+ throughout procedure.
+ * gcc.target/mips/abi-o64-long64.c: Require -mno-abicalls
+ instead of addressing=absolute.
+
+2011-10-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.target/mips/stack-1.c: New test.
+
+2011-10-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.dg/pr49696.c: New test.
+
2011-10-02 Jan Hubicka <jh@suse.cz>
* gcc.dg/ipa/ctor-empty-1.c: Update dump file.
@@ -48,7 +1090,7 @@
2011-09-30 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
- * gcc.target/arm/pr42835.c: Add -fno-tree-tail-merge.
+ * gcc.target/arm/pr42835.c: Add -fno-tree-tail-merge.
2011-09-30 David S. Miller <davem@davemloft.net>
@@ -103,8 +1145,8 @@
PR testsuite/50485
* gcc.target/i386/sse4_1-blendps.c: Include <stdlib.h>.
(TEST): Initialize src3 with random floats.
- * gcc.target/i386/sse4_1-blendps-2.c (sse4_1_test): Remove field i from
- union src3. Initialize src3 with random floats.
+ * gcc.target/i386/sse4_1-blendps-2.c (sse4_1_test): Remove field i
+ from union src3. Initialize src3 with random floats.
2011-09-27 Oleg Endo <oleg.endo@t-online.de>
@@ -464,8 +1506,7 @@
2011-09-20 H.J. Lu <hongjiu.lu@intel.com>
PR testsuite/50469
- * gfortran.dg/storage_size_2.f08: Replace "must be be" with
- "must be".
+ * gfortran.dg/storage_size_2.f08: Replace "must be be" with "must be".
2011-09-20 Jason Merrill <jason@redhat.com>
@@ -851,8 +1892,7 @@
gcc.dg/vect/vect-54.c, gcc.dg/vect/vect-46.c, gcc.dg/vect/vect-48.c,
gcc.dg/vect/vect-96.c, gcc.dg/vect/vect-multitypes-3.c,
gcc.dg/vect/vect-40.c: Likewise.
- * gcc.dg/vect/vect-outer-5.c: Remove quad-vectors option as
- redundant.
+ * gcc.dg/vect/vect-outer-5.c: Remove quad-vectors option as redundant.
* gcc.dg/vect/vect-109.c, gcc.dg/vect/vect-peel-1.c,
gcc.dg/vect/vect-peel-2.c, gcc.dg/vect/slp-25.c,
gcc.dg/vect/vect-multitypes-1.c, gcc.dg/vect/slp-3.c,
@@ -909,8 +1949,8 @@
2011-09-05 Georg-Johann Lay <avr@gjlay.de>
- * gcc.dg/ipa/ipcp-3.c (mark_cell): Use mask 1 << 14 instead of 1
- << 18 to avoid warning on int=16 platforms..
+ * gcc.dg/ipa/ipcp-3.c (mark_cell): Use mask 1 << 14 instead of 1 << 18
+ to avoid warning on int=16 platforms..
2011-09-05 Jakub Jelinek <jakub@redhat.com>
@@ -6026,6 +7066,7 @@
* gcc.dg/vect/pr49038.c: New test.
2011-05-26 Fabien Chêne <fabien@gcc.gnu.org>
+
* g++.dg/init/pr25811-3.C: New.
* g++.dg/init/pr25811-4.C: New.
@@ -6100,7 +7141,7 @@
2011-05-24 Nicola Pero <nicola.pero@meta-innovation.com>
PR libobjc/48177
- * objc.dg/pr48177.m: New testcase.
+ * objc.dg/pr48177.m: New testcase.
2011-05-24 Nicola Pero <nicola.pero@meta-innovation.com>
@@ -7114,6 +8155,11 @@
* gfortran.dg/char4_iunit_2.f03: Adjust test.
* gfortran.dg/real_const_3.f90: Adjust test.
+2011-04-29 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/tree-ssa/inline-10.c: New testcase.
+ * gcc.dg/tree-ssa/inline-9.c: Disable partial inlining.
+
2011-04-28 Xinliang David Li <davidxl@google.com>
* gcc.dg/tree-prof/prof-robust-1.c: New test.
diff --git a/gcc/testsuite/c-c++-common/cxxbitfields-2.c b/gcc/testsuite/c-c++-common/cxxbitfields-2.c
deleted file mode 100644
index b98b56daa91..00000000000
--- a/gcc/testsuite/c-c++-common/cxxbitfields-2.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-/* Test that we don't store past VAR.K. */
-
-struct S
-{
- volatile int i;
- volatile int j: 32;
- volatile int k: 15;
- volatile char c[2];
-} var;
-
-void setit()
-{
- var.k = 13;
-}
-
-/* { dg-final { scan-assembler-not "movl.*, var" } } */
diff --git a/gcc/testsuite/c-c++-common/cxxbitfields-4.c b/gcc/testsuite/c-c++-common/cxxbitfields-4.c
deleted file mode 100644
index 7023b31654a..00000000000
--- a/gcc/testsuite/c-c++-common/cxxbitfields-4.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-struct bits
-{
- char a;
- int b:7;
- int c:9;
- unsigned char d;
-} x;
-
-/* Store into <c> should not clobber <d>. */
-void update_c(struct bits *p, int val)
-{
- p -> c = val;
-}
-
-/* { dg-final { scan-assembler "mov\[bw\]" } } */
diff --git a/gcc/testsuite/c-c++-common/cxxbitfields-5.c b/gcc/testsuite/c-c++-common/cxxbitfields-5.c
deleted file mode 100644
index fba604fccc7..00000000000
--- a/gcc/testsuite/c-c++-common/cxxbitfields-5.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-#include <stdlib.h>
-
-struct bits
-{
- char a;
- int b:7;
- int c:9;
- unsigned char d;
-} x;
-
-struct bits *p;
-
-static void allocit()
-{
- p = (struct bits *) malloc (sizeof (struct bits));
-}
-
-/* Store into <c> should not clobber <d>. */
-/* We should not use a 32-bit move to store into p->, but a smaller move. */
-void foo()
-{
- allocit();
- p -> c = 55;
-}
-
-/* { dg-final { scan-assembler "mov\[bw\]" } } */
diff --git a/gcc/testsuite/c-c++-common/cxxbitfields.c b/gcc/testsuite/c-c++-common/cxxbitfields.c
deleted file mode 100644
index 43c840b15eb..00000000000
--- a/gcc/testsuite/c-c++-common/cxxbitfields.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-/* Test that we don't store past VAR.A. */
-
-struct S
-{
- volatile unsigned int a : 4;
- unsigned char b;
- unsigned int c : 6;
-} var;
-
-void set_a()
-{
- var.a = 12;
-}
-
-/* { dg-final { scan-assembler-not "movl.*, var" } } */
diff --git a/gcc/testsuite/c-c++-common/simulate-thread/bitfields-1.c b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-1.c
new file mode 100644
index 00000000000..9ca3a67f3c4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-1.c
@@ -0,0 +1,71 @@
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+/* Test that we don't store past VAR.A. */
+
+struct S
+{
+ volatile unsigned int a : 4;
+ unsigned char b;
+ unsigned int c : 6;
+} var = { 1, 2, 3 };
+
+static int global = 0;
+
+/* Called before each instruction, simulating another thread
+ executing. */
+void simulate_thread_other_threads()
+{
+ global++;
+ var.b = global;
+ /* Don't go past the 6 bits var.c can hold. */
+ var.c = global % 64;
+}
+
+/* Called after each instruction. Returns 1 if any inconsistency is
+ found, 0 otherwise. */
+int simulate_thread_step_verify()
+{
+ int ret = 0;
+ if (var.b != global)
+ {
+ printf("FAIL: invalid intermediate value for <b>.\n");
+ ret = 1;
+ }
+ if (var.c != global % 64)
+ {
+ printf("FAIL: invalid intermediate value for <c>.\n");
+ ret = 1;
+ }
+ return ret;
+}
+
+/* Called at the end of the program (simulate_thread_fini == 1). Verifies
+ the state of the program and returns 1 if any inconsistency is
+ found, 0 otherwise. */
+int simulate_thread_final_verify()
+{
+ if (var.a != 12)
+ {
+ printf("FAIL: invalid final result for <a>.\n");
+ return 1;
+ }
+ return 0;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ var.a = 12;
+}
+
+int main()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/simulate-thread/bitfields-2.c b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-2.c
new file mode 100644
index 00000000000..392f779bad5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-2.c
@@ -0,0 +1,59 @@
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+/* Test that we don't store past VAR.K. */
+
+struct S
+{
+ volatile int i;
+ volatile int j: 32;
+ volatile int k: 15;
+ volatile unsigned char c[2];
+} var;
+
+static int global = 0;
+
+void simulate_thread_other_threads()
+{
+ global++;
+ var.c[0] = global % 256;
+ var.c[1] = global % 256;
+}
+
+int simulate_thread_step_verify()
+{
+ if (var.c[0] != global % 256
+ || var.c[1] != global % 256)
+ {
+ printf("FAIL: invalid intermediate result for <var.c[]>.\n");
+ return 1;
+ }
+ return 0;
+}
+
+int simulate_thread_final_verify()
+{
+ if (var.k != 13)
+ {
+ printf("FAIL: invalid final result\n");
+ return 1;
+ }
+ return 0;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ var.k = 13;
+}
+
+int main()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/simulate-thread/bitfields-3.c b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-3.c
new file mode 100644
index 00000000000..78f4d75c8ba
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-3.c
@@ -0,0 +1,63 @@
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+/* Store into <c> should not clobber <d>. */
+
+struct bits
+{
+ char a;
+ int b:7;
+ int c:9;
+ unsigned char d;
+} var;
+
+static int global = 0;
+
+void simulate_thread_other_threads()
+{
+ global++;
+ var.d = global;
+}
+
+int simulate_thread_step_verify()
+{
+ if (var.d != global)
+ {
+ printf("FAIL: invalid intermediate result\n");
+ return 1;
+ }
+ return 0;
+}
+
+int simulate_thread_final_verify()
+{
+ if (var.c != 5)
+ {
+ printf("FAIL: invalid final result\n");
+ return 1;
+ }
+ return 0;
+}
+
+__attribute__((noinline))
+void update_c(struct bits *p, int val)
+{
+ p -> c = val;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ update_c(&var, 5);
+}
+
+int main()
+{
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/simulate-thread/bitfields-4.c b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-4.c
new file mode 100644
index 00000000000..cd6badf3329
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/simulate-thread/bitfields-4.c
@@ -0,0 +1,60 @@
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+struct bits
+{
+ char a;
+ int b:7;
+ int c:9;
+ unsigned char d;
+} *p;
+
+static int global = 0;
+
+void simulate_thread_other_threads()
+{
+ global++;
+ p->d = global % 256;
+}
+
+int simulate_thread_step_verify()
+{
+ if (p->d != global % 256)
+ {
+ printf("FAIL: invalid intermediate result\n");
+ return 1;
+ }
+ return 0;
+}
+
+int simulate_thread_final_verify()
+{
+ if (p->c != 55)
+ {
+ printf("FAIL: invalid final result\n");
+ return 1;
+ }
+ return 0;
+}
+
+/* Store into <c> should not clobber <d>. */
+/* We should not use a 32-bit move to store into p->, but a smaller move. */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ p -> c = 55;
+}
+
+
+int main()
+{
+ p = (struct bits *) calloc (1, sizeof (struct bits));
+ simulate_thread_main();
+ simulate_thread_done();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
index db0e973a7a0..5ad3f4409f6 100644
--- a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
+++ b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
@@ -47,7 +47,7 @@ const char *dg_options[] = {
"/* { dg-options \"%s-I%s\" } */\n",
"/* { dg-options \"%s-I%s -mno-mmx -Wno-abi\" { target i?86-*-* x86_64-*-* } } */\n",
"/* { dg-options \"%s-I%s -fno-common\" { target alpha*-dec-osf* hppa*-*-hpux* powerpc*-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n",
-"/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* } } */\n",
+"/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* i?86-*-mingw32* x86_64-*-mingw32* i?86-*-cygwin* } } */\n",
"/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n",
"/* { dg-options \"%s-I%s -mlongcalls -mtext-section-literals\" { target xtensa*-*-* } } */\n"
#define NDG_OPTIONS (sizeof (dg_options) / sizeof (dg_options[0]))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
new file mode 100644
index 00000000000..75b2fc4634e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
@@ -0,0 +1,9 @@
+// { dg-options -std=c++0x }
+
+struct A { constexpr operator int() { return 42; } };
+
+template<class T>
+struct B {
+ static const int versionConst = A();
+ enum { versionEnum = versionConst };
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
index 5d536a97eff..9b8c697abad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
@@ -2,13 +2,12 @@
// { dg-options -std=c++0x }
struct A {
- A(A&&) = default; // { dg-message "A::A|no known conversion" }
+ A(A&&) = default;
};
struct B {
const A a;
B(const B&) = default;
- B(B&&) = default; // { dg-error "implicitly deleted|no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+ B(B&&) = default; // { dg-error "implicitly deleted|use of deleted" }
};
void g(B); // { dg-error "argument 1" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
index 3e740331d8a..30a4a7c7d01 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
@@ -12,7 +12,7 @@ struct X {
X(X&&);
};
-X::X(X&&)=default; // { dg-error "implicitly deleted" }
+X::X(X&&)=default; // { dg-message "implicitly deleted" }
// { dg-error "does not have a move constructor" "" { target *-*-* } 15 }
X f() {
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted31.C b/gcc/testsuite/g++.dg/cpp0x/defaulted31.C
new file mode 100644
index 00000000000..de6a29854a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted31.C
@@ -0,0 +1,16 @@
+// PR c++/39164
+// { dg-options -std=c++0x }
+
+struct A
+{
+ A() { } // { dg-error "defined" }
+ ~A() = default; // { dg-error "defaulted" }
+};
+
+A::A() = default; // { dg-error "redefinition" }
+A::~A() noexcept (true) { } // { dg-error "defaulted" }
+
+int main()
+{
+ A a;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted32.C b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C
new file mode 100644
index 00000000000..351cdae1102
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C
@@ -0,0 +1,21 @@
+// PR c++/50531
+// { dg-options -std=c++0x }
+
+template <typename T>
+class DataFilter
+{
+ public:
+ inline virtual ~DataFilter();
+};
+
+template<typename T>
+inline DataFilter<T>::~DataFilter() = default;
+
+class ARCalculator : public DataFilter<ARCalculator>
+{
+ public:
+ virtual void dataStart(int, int);
+};
+
+void ARCalculator::dataStart(int, int)
+{}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
index 861fe201f10..c3f6b85e247 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
@@ -3,13 +3,13 @@ struct S
{
S();
private:
- S(S const &&); // { dg-error "" }
- S & operator=(S const &&); // { dg-error "" }
+ S(S const &&);
+ S & operator=(S const &&);
};
void f()
{
S a;
- S b(a); // { dg-error "" }
- a = b; // { dg-error "" }
+ S b(a); // { dg-error "deleted" }
+ a = b; // { dg-error "deleted" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit12.C b/gcc/testsuite/g++.dg/cpp0x/implicit12.C
new file mode 100644
index 00000000000..da806e006a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit12.C
@@ -0,0 +1,54 @@
+// PR c++/50500
+// { dg-options "-std=c++0x" }
+
+// If a class declares move operations, the implicitly declared copy
+// operations are deleted.
+struct A
+{
+ A();
+ A(A&&);
+ A& operator=(A&&);
+};
+
+// But they can still be explicitly defaulted.
+struct B
+{
+ B();
+ B(B&&);
+ B(const B&) = default;
+ B& operator=(B&&);
+ B& operator=(const B&) = default;
+};
+
+struct C
+{
+ C();
+ C(C&&);
+};
+
+struct D
+{
+ D();
+ D& operator=(D&&);
+};
+
+int main()
+{
+ A a;
+ A a2 (a); // { dg-error "deleted" }
+ a2 = a; // { dg-error "deleted" }
+
+ B b;
+ B b2 (b);
+ b2 = b;
+
+ C c;
+ C c2(c); // { dg-error "deleted" }
+ c2 = c; // { dg-error "deleted" }
+
+ D d;
+ D d2(d); // { dg-error "deleted" }
+ d2 = d; // { dg-error "deleted" }
+}
+
+// { dg-prune-output "because" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit4.C b/gcc/testsuite/g++.dg/cpp0x/implicit4.C
index f97eb7549f9..47fd56a5252 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit4.C
@@ -2,14 +2,13 @@
// constructor to be deleted.
// { dg-options "-std=c++0x" }
-struct A
+struct A // { dg-message "declares a move" }
{
- A(); // { dg-message "A::A|candidate expects" }
- A(A&&); // { dg-message "A::A|no known conversion" }
+ A();
+ A(A&&);
};
-struct B: A // { dg-error "implicit|no match" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 11 }
+struct B: A // { dg-error "use of deleted" }
{
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit5.C b/gcc/testsuite/g++.dg/cpp0x/implicit5.C
index f25c08530db..d25294831e3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit5.C
@@ -1,19 +1,19 @@
-// Test that the default B copy constructor calls the A member template
-// constructor.
+// Test that the default B copy constructor calls the deleted A
+// copy constructor.
// { dg-options -std=c++0x }
-struct A
+struct A // { dg-message "declares a move" }
{
A() = default;
A(A&&) = default;
template <class T>
- A(const T& t) { t.i; } // { dg-error "no member" }
+ A(const T& t) { t.i; }
};
-struct B: A { };
+struct B: A { }; // { dg-error "implicitly|use of deleted" }
int main()
{
B b;
- B b2(b);
+ B b2(b); // { dg-error "deleted" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit8.C b/gcc/testsuite/g++.dg/cpp0x/implicit8.C
index 2f3febae8b2..c949af21050 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit8.C
@@ -1,9 +1,6 @@
// The hack for PR c++/44909 breaks this testcase. We need feedback
// from the C++ committee to know how to proceed.
// { dg-options -std=c++0x }
-// { dg-prune-output "implicitly deleted" }
-// { dg-prune-output "cannot bind" }
-// { dg-prune-output "initializing argument" }
struct A
{
@@ -28,7 +25,8 @@ struct B
// subobject of C should use B(const BP&). But we ignore that constructor
// in order to break the cycle in 44909. Perhaps the move ctor shouldn't
// suppress the copy ctor?
-struct C: A, B { };
+// As of DR 1082, it doesn't suppress it.
+struct C: A, B { }; // { dg-error "use of deleted" }
C c;
-C c2(c); // { dg-bogus "deleted" "" { xfail *-*-* } }
+C c2(c); // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C
new file mode 100644
index 00000000000..b5ba0663754
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C
@@ -0,0 +1,14 @@
+// PR c++/50437
+// { dg-options -std=c++0x }
+
+template <typename T>
+void f()
+{
+ auto g = [](T t){ return t == 0; };
+ g(T());
+}
+
+int main()
+{
+ f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C
new file mode 100644
index 00000000000..82cc98423ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C
@@ -0,0 +1,15 @@
+// PR c++/50736
+// { dg-options "-std=c++0x -pedantic-errors" }
+
+int i;
+void f();
+typedef int T;
+
+int main()
+{
+ [i]{}; // { dg-error "non-automatic" }
+ [f]{}; // { dg-error "non-variable" }
+ [T]{}; // { dg-error "non-variable" }
+}
+
+struct A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
index 8d7d093dc40..6468f18a0ac 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
@@ -9,7 +9,7 @@ decltype(F()) run(F f) // { dg-message "note" }
int main()
{
- auto l = []() { return 5; }; // { dg-error "lambda closure type" }
+ auto l = []() { return 5; }; // { dg-message "lambda closure type" }
run(l); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 14 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/not_special.C b/gcc/testsuite/g++.dg/cpp0x/not_special.C
index 6d73bd086ca..2b510bb9a1b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/not_special.C
+++ b/gcc/testsuite/g++.dg/cpp0x/not_special.C
@@ -1,8 +1,8 @@
// I, Howard Hinnant, hereby place this code in the public domain.
// Test that move constructor and move assignement are special.
-// That is, their presence should inhibit compiler generated
-// copy ctor or assignment.
+// That is, their presence should cause compiler declared
+// copy ctor or assignment to be deleted.
// { dg-options "-std=c++0x" }
@@ -24,12 +24,12 @@ struct base
base& operator=(const base&) {++assign; return *this;}
};
-struct derived
+struct derived // { dg-message "declares a move" }
: base
{
derived() {}
- derived(derived&&) {} // { dg-error "argument 1" }
- derived& operator=(derived&&) {return *this;} // { dg-error "argument 1" }
+ derived(derived&&) {}
+ derived& operator=(derived&&) {return *this;}
};
int test1()
@@ -37,11 +37,11 @@ int test1()
derived d;
derived d2(static_cast<derived&&>(d)); // should not call base::(const base&)
assert(copy == 0);
- derived d3(d); // { dg-error "lvalue" }
+ derived d3(d); // { dg-error "deleted" }
assert(copy == 1);
d2 = static_cast<derived&&>(d); // should not call base::operator=
assert(assign == 0);
- d3 = d; // { dg-error "lvalue" }
+ d3 = d; // { dg-error "deleted" }
assert(assign == 1);
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C
new file mode 100644
index 00000000000..ddf9f04c580
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C
@@ -0,0 +1,10 @@
+// PR c++/50707
+// { dg-options -std=c++0x }
+
+int g;
+
+struct S {
+ int const v=g;
+};
+
+S s;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C
new file mode 100644
index 00000000000..526f29ae285
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C
@@ -0,0 +1,14 @@
+// PR c++/50563
+// { dg-options -std=c++0x }
+
+struct S1 {
+ int a{10}, b{20}; // OK
+};
+
+struct S2 {
+ int a, b = 20; // OK
+};
+
+struct S3 {
+ int a = 10, b = 20;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C
new file mode 100644
index 00000000000..27b0aa5f9da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C
@@ -0,0 +1,14 @@
+// PR c++/50614
+// { dg-options "-std=c++0x -fcompare-debug" }
+
+struct A
+{
+ int f ();
+};
+
+template <int> struct B : A
+{
+ int i = this->f ();
+};
+
+B<0> b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C
new file mode 100644
index 00000000000..62803b0819e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C
@@ -0,0 +1,20 @@
+// { dg-options -std=c++0x }
+
+struct X
+{
+ int x = 5;
+ int f() { return x; }
+};
+struct Y : X
+{
+ int y = this->x;
+};
+template <class T> struct Z : T
+{
+ int y = this->f();
+};
+int main()
+{
+ Y foo;
+ Z<X> bar;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for22.C b/gcc/testsuite/g++.dg/cpp0x/range-for22.C
new file mode 100644
index 00000000000..5fef5e6accb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for22.C
@@ -0,0 +1,5 @@
+// { dg-options -std=c++0x }
+
+template<int I> void f() {
+ for (auto i: {I} );
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
index 2765b5f3c30..cbce7c4ddd7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
@@ -5,22 +5,22 @@
int move_construct = 0;
int move_assign = 0;
-struct base2
+struct base2 // { dg-message "declares a move" }
{
base2() {}
- base2(base2&&) {++move_construct;} // { dg-error "argument 1" }
- base2& operator=(base2&&) {++move_assign; return *this;} // { dg-error "argument 1" }
+ base2(base2&&) {++move_construct;}
+ base2& operator=(base2&&) {++move_assign; return *this;}
};
int test2()
{
base2 b;
- base2 b2(b); // { dg-error "lvalue" }
+ base2 b2(b); // { dg-error "deleted" }
assert(move_construct == 0);
base2 b3(static_cast<base2&&>(b));
base2 b4 = static_cast<base2&&>(b);
assert(move_construct == 2);
- b = b2; // { dg-error "lvalue" }
+ b = b2; // { dg-error "deleted" }
assert(move_assign == 0);
b = static_cast<base2&&>(b2);
assert(move_assign == 1);
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv1n.C b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
index 5224d3eb70e..68305ebc9b4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv1n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -35,9 +35,9 @@ one sink_1_1( A&); // { dg-error "" }
int test1_1()
{
A a;
- const A ca = a; // { dg-error "cannot bind" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "cannot bind" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_1(ca); // { dg-error "invalid initialization" }
sink_1_1(va); // { dg-error "invalid initialization" }
sink_1_1(cva); // { dg-error "invalid initialization" }
@@ -53,9 +53,9 @@ two sink_1_2(const A&); // { dg-error "" }
int test1_2()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_2(va); // { dg-error "invalid initialization" }
sink_1_2(cva); // { dg-error "invalid initialization" }
sink_1_2(v_source()); // { dg-error "invalid initialization" }
@@ -68,9 +68,9 @@ three sink_1_3(volatile A&); // { dg-error "" }
int test1_3()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_3(ca); // { dg-error "invalid initialization" }
sink_1_3(cva); // { dg-error "invalid initialization" }
sink_1_3(source()); // { dg-error "invalid initialization" }
@@ -85,9 +85,9 @@ four sink_1_4(const volatile A&); // { dg-error "" }
int test1_4()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_4(source()); // { dg-error "invalid initialization" }
sink_1_4(c_source()); // { dg-error "invalid initialization" }
sink_1_4(v_source()); // { dg-error "invalid initialization" }
@@ -100,9 +100,9 @@ five sink_1_5( A&&); // { dg-error "" }
int test1_5()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_5(a); // { dg-error "lvalue" }
sink_1_5(ca); // { dg-error "invalid initialization" }
sink_1_5(va); // { dg-error "invalid initialization" }
@@ -118,9 +118,9 @@ six sink_1_6(const A&&); // { dg-error "" }
int test1_6()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_6(a); // { dg-error "lvalue" }
sink_1_6(ca); // { dg-error "lvalue" }
sink_1_6(va); // { dg-error "invalid initialization" }
@@ -135,9 +135,9 @@ seven sink_1_7(volatile A&&); // { dg-error "" }
int test1_7()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_7(a); // { dg-error "lvalue" }
sink_1_7(ca); // { dg-error "invalid initialization" }
sink_1_7(va); // { dg-error "lvalue" }
@@ -152,9 +152,9 @@ eight sink_1_8(const volatile A&&); // { dg-error "" }
int test1_8()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_8(a); // { dg-error "lvalue" }
sink_1_8(ca); // { dg-error "lvalue" }
sink_1_8(va); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv2n.C b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
index 2b3a9c06ae9..a9d37415e07 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv2n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -36,9 +36,9 @@ two sink_2_12(const A&); // { dg-message "note|argument" }
int test2_12()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_12(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 42 }
sink_2_12(cva); // { dg-error "no match" }
@@ -56,9 +56,9 @@ three sink_2_13(volatile A&); // { dg-message "note|argument" }
int test2_13()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_13(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 62 }
sink_2_13(cva); // { dg-error "no match" }
@@ -80,9 +80,9 @@ four sink_2_14(const volatile A&); // { dg-message "note|argument" }
int test2_14()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_14(source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 86 }
sink_2_14(c_source()); // { dg-error "no match" }
@@ -100,9 +100,9 @@ five sink_2_15( A&&); // { dg-message "note|argument" }
int test2_15()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_15(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 106 }
sink_2_15(va); // { dg-error "no match" }
@@ -124,9 +124,9 @@ six sink_2_16(const A&&); // { dg-message "note|argument" }
int test2_16()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_16(ca); // { dg-error "lvalue" }
sink_2_16(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 131 }
@@ -145,9 +145,9 @@ seven sink_2_17(volatile A&&); // { dg-message "note|argument" }
int test2_17()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_17(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 151 }
sink_2_17(va); // { dg-error "lvalue" }
@@ -166,9 +166,9 @@ eight sink_2_18(const volatile A&&); // { dg-error "argument" }
int test2_18()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_18(ca); // { dg-error "lvalue" }
sink_2_18(va); // { dg-error "lvalue" }
sink_2_18(cva); // { dg-error "lvalue" }
@@ -180,9 +180,9 @@ three sink_2_23(volatile A&); // { dg-message "note|argument" }
int test2_23()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_23(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 186 }
sink_2_23(cva); // { dg-error "no match" }
@@ -200,9 +200,9 @@ four sink_2_24(const volatile A&); // { dg-message "note|argument" }
int test2_24()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_24(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 206 }
sink_2_24(cv_source()); // { dg-error "no match" }
@@ -216,9 +216,9 @@ four sink_2_34(const volatile A&); // { dg-message "note|argument" }
int test2_34()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_34(source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 222 }
sink_2_34(c_source()); // { dg-error "no match" }
@@ -236,9 +236,9 @@ five sink_2_25( A&&); // { dg-message "note|argument" }
int test2_25()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_25(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 242 }
sink_2_25(cva); // { dg-error "no match" }
@@ -256,9 +256,9 @@ six sink_2_26(const A&&); // { dg-message "note|argument" }
int test2_26()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_26(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 262 }
sink_2_26(cva); // { dg-error "no match" }
@@ -276,9 +276,9 @@ seven sink_2_27(volatile A&&); // { dg-message "note|argument" }
int test2_27()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_27(va); // { dg-error "lvalue" }
sink_2_27(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 283 }
@@ -293,9 +293,9 @@ eight sink_2_28(const volatile A&&); // { dg-error "argument" }
int test2_28()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_28(va); // { dg-error "lvalue" }
sink_2_28(cva); // { dg-error "lvalue" }
}
@@ -306,9 +306,9 @@ five sink_2_35( A&&); // { dg-message "note|argument" }
int test2_35()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_35(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 312 }
sink_2_35(cva); // { dg-error "no match" }
@@ -328,9 +328,9 @@ six sink_2_36(const A&&); // { dg-message "note|argument" }
int test2_36()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_36(ca); // { dg-error "lvalue" }
sink_2_36(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 335 }
@@ -347,9 +347,9 @@ seven sink_2_37(volatile A&&); // { dg-message "note|argument" }
int test2_37()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_37(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 353 }
sink_2_37(cva); // { dg-error "no match" }
@@ -367,9 +367,9 @@ eight sink_2_38(const volatile A&&); // { dg-error "argument" }
int test2_38()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_38(ca); // { dg-error "lvalue" }
sink_2_38(cva); // { dg-error "lvalue" }
}
@@ -380,9 +380,9 @@ five sink_2_45( A&&); // { dg-message "note|argument" }
int test2_45()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_45(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 386 }
sink_2_45(v_source()); // { dg-error "no match" }
@@ -398,9 +398,9 @@ six sink_2_46(const A&&); // { dg-message "note|argument" }
int test2_46()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_46(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 404 }
sink_2_46(cv_source()); // { dg-error "no match" }
@@ -414,9 +414,9 @@ seven sink_2_47(volatile A&&); // { dg-message "note|argument" }
int test2_47()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_47(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 420 }
sink_2_47(cv_source()); // { dg-error "no match" }
@@ -430,9 +430,9 @@ six sink_2_56(const A&&); // { dg-message "note|argument" }
int test2_56()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_56(a); // { dg-error "lvalue" }
sink_2_56(ca); // { dg-error "lvalue" }
sink_2_56(va); // { dg-error "no match" }
@@ -452,9 +452,9 @@ seven sink_2_57(volatile A&&); // { dg-message "note|argument" }
int test2_57()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_57(a); // { dg-error "lvalue" }
sink_2_57(va); // { dg-error "lvalue" }
sink_2_57(ca); // { dg-error "no match" }
@@ -474,9 +474,9 @@ eight sink_2_58(const volatile A&&); // { dg-error "argument" }
int test2_58()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_58(a); // { dg-error "lvalue" }
sink_2_58(ca); // { dg-error "lvalue" }
sink_2_58(va); // { dg-error "lvalue" }
@@ -489,9 +489,9 @@ seven sink_2_67(volatile A&&); // { dg-message "note|argument" }
int test2_67()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_67(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 495 }
sink_2_67(ca); // { dg-error "lvalue" }
@@ -511,9 +511,9 @@ eight sink_2_68(const volatile A&&); // { dg-error "argument" }
int test2_68()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_68(a); // { dg-error "lvalue" }
sink_2_68(ca); // { dg-error "lvalue" }
sink_2_68(va); // { dg-error "lvalue" }
@@ -526,9 +526,9 @@ eight sink_2_78(const volatile A&&); // { dg-error "argument" }
int test2_78()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_78(a); // { dg-error "lvalue" }
sink_2_78(ca); // { dg-error "lvalue" }
sink_2_78(va); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv3n.C b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
index 637716f9b44..14b810ae68d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv3n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -37,9 +37,9 @@ three sink_3_123(volatile A&); // { dg-message "three sink_3_123|no known
int test3_123()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_123(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 43 }
sink_3_123(v_source()); // { dg-error "no match" }
@@ -60,9 +60,9 @@ four sink_3_124(const volatile A&); // { dg-message "four sink_3_124|no known
int test3_124()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_124(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 66 }
sink_3_124(cv_source()); // { dg-error "no match" }
@@ -73,9 +73,9 @@ int test3_124()
int test3_125()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_125(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 79 }
sink_3_125(cva); // { dg-error "no match" }
@@ -94,9 +94,9 @@ six sink_3_126(const A&&); // { dg-message "six sink_3_126|no known
int test3_126()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_126(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 100 }
sink_3_126(cva); // { dg-error "no match" }
@@ -115,9 +115,9 @@ seven sink_3_127(volatile A&&); // { dg-message "seven sink_3_127|no know
int test3_127()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_127(va); // { dg-error "lvalue" }
sink_3_127(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 122 }
@@ -133,9 +133,9 @@ eight sink_3_128(const volatile A&&); // { dg-message "" }
int test3_128()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_128(va); // { dg-error "lvalue" }
sink_3_128(cva); // { dg-error "lvalue" }
@@ -148,9 +148,9 @@ four sink_3_134(const volatile A&); // { dg-message "four sink_3_134|no known
int test3_134()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_134(source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 154 }
sink_3_134(c_source()); // { dg-error "no match" }
@@ -169,9 +169,9 @@ five sink_3_135( A&&); // { dg-message "five sink_3_135|no known
int test3_135()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_135(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 175 }
sink_3_135(cva); // { dg-error "no match" }
@@ -192,9 +192,9 @@ six sink_3_136(const A&&); // { dg-message "" }
int test3_136()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_136(ca); // { dg-error "lvalue" }
sink_3_136(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 199 }
@@ -212,9 +212,9 @@ seven sink_3_137(volatile A&&); // { dg-message "note" }
int test3_137()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_137(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 218 }
sink_3_137(cva); // { dg-error "no match" }
@@ -233,9 +233,9 @@ eight sink_3_138(const volatile A&&); // { dg-message "" }
int test3_138()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_138(ca); // { dg-error "lvalue" }
sink_3_138(cva); // { dg-error "lvalue" }
return 0;
@@ -248,9 +248,9 @@ five sink_3_145( A&&); // { dg-message "note" }
int test3_145()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_145(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 254 }
sink_3_145(v_source()); // { dg-error "no match" }
@@ -267,9 +267,9 @@ six sink_3_146(const A&&); // { dg-message "note" }
int test3_146()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_146(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 273 }
sink_3_146(cv_source()); // { dg-error "no match" }
@@ -284,9 +284,9 @@ seven sink_3_147(volatile A&&); // { dg-message "note" }
int test3_147()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_147(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 290 }
sink_3_147(cv_source()); // { dg-error "no match" }
@@ -301,9 +301,9 @@ six sink_3_156(const A&&); // { dg-message "" }
int test3_156()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_156(ca); // { dg-error "lvalue" }
sink_3_156(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 308 }
@@ -323,9 +323,9 @@ seven sink_3_157(volatile A&&); // { dg-message "" }
int test3_157()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_157(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 329 }
sink_3_157(va); // { dg-error "lvalue" }
@@ -345,9 +345,9 @@ eight sink_3_158(const volatile A&&); // { dg-message "" }
int test3_158()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_158(ca); // { dg-error "lvalue" }
sink_3_158(va); // { dg-error "lvalue" }
sink_3_158(cva); // { dg-error "lvalue" }
@@ -361,9 +361,9 @@ seven sink_3_167(volatile A&&); // { dg-message "" }
int test3_167()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_167(ca); // { dg-error "lvalue" }
sink_3_167(va); // { dg-error "lvalue" }
sink_3_167(cva); // { dg-error "no match" }
@@ -382,9 +382,9 @@ eight sink_3_168(const volatile A&&); // { dg-message "" }
int test3_168()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_168(ca); // { dg-error "lvalue" }
sink_3_168(va); // { dg-error "lvalue" }
sink_3_168(cva); // { dg-error "lvalue" }
@@ -398,9 +398,9 @@ eight sink_3_178(const volatile A&&); // { dg-message "" }
int test3_178()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_178(ca); // { dg-error "lvalue" }
sink_3_178(va); // { dg-error "lvalue" }
sink_3_178(cva); // { dg-error "lvalue" }
@@ -414,9 +414,9 @@ four sink_3_234(const volatile A&); // { dg-message "note" }
int test3_234()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_234(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 420 }
sink_3_234(v_source()); // { dg-error "no match" }
@@ -433,9 +433,9 @@ five sink_3_235( A&&); // { dg-message "note" }
int test3_235()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_235(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 439 }
sink_3_235(cva); // { dg-error "no match" }
@@ -454,9 +454,9 @@ six sink_3_236(const A&&); // { dg-message "note" }
int test3_236()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_236(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 460 }
sink_3_236(cva); // { dg-error "no match" }
@@ -475,9 +475,9 @@ seven sink_3_237(volatile A&&); // { dg-message "note" }
int test3_237()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_237(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 481 }
sink_3_237(cva); // { dg-error "no match" }
@@ -494,9 +494,9 @@ eight sink_3_238(const volatile A&&); // { dg-message "eight sink_3_238|no know
int test3_238()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_238(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 500 }
sink_3_238(cva); // { dg-error "lvalue" }
@@ -510,9 +510,9 @@ five sink_3_245( A&&); // { dg-message "five sink_3_245|no known
int test3_245()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_245(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 516 }
sink_3_245(cv_source()); // { dg-error "no match" }
@@ -527,9 +527,9 @@ six sink_3_246(const A&&); // { dg-message "six sink_3_246|no known
int test3_246()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_246(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 533 }
sink_3_246(cv_source()); // { dg-error "no match" }
@@ -544,9 +544,9 @@ seven sink_3_247(volatile A&&); // { dg-message "seven sink_3_247|no know
int test3_247()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_247(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 550 }
return 0;
@@ -559,9 +559,9 @@ six sink_3_256(const A&&); // { dg-message "six sink_3_256|no known
int test3_256()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_256(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 565 }
sink_3_256(cva); // { dg-error "no match" }
@@ -580,9 +580,9 @@ seven sink_3_257(volatile A&&); // { dg-message "seven sink_3_257|no know
int test3_257()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_257(va); // { dg-error "lvalue" }
sink_3_257(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 587 }
@@ -598,9 +598,9 @@ eight sink_3_258(const volatile A&&); // { dg-message "" }
int test3_258()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_258(va); // { dg-error "lvalue" }
sink_3_258(cva); // { dg-error "lvalue" }
return 0;
@@ -613,9 +613,9 @@ seven sink_3_267(volatile A&&); // { dg-message "seven sink_3_267|no know
int test3_267()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_267(va); // { dg-error "lvalue" }
sink_3_267(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 620 }
@@ -633,9 +633,9 @@ eight sink_3_268(const volatile A&&); // { dg-message "" }
int test3_268()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_268(va); // { dg-error "lvalue" }
sink_3_268(cva); // { dg-error "lvalue" }
return 0;
@@ -648,9 +648,9 @@ eight sink_3_278(const volatile A&&); // { dg-message "" }
int test3_278()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_278(va); // { dg-error "lvalue" }
sink_3_278(cva); // { dg-error "lvalue" }
return 0;
@@ -663,9 +663,9 @@ five sink_3_345( A&&); // { dg-message "five sink_3_345|no known
int test3_345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_345(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 669 }
sink_3_345(v_source()); // { dg-error "no match" }
@@ -682,9 +682,9 @@ six sink_3_346(const A&&); // { dg-message "six sink_3_346|no known
int test3_346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_346(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 688 }
sink_3_346(cv_source()); // { dg-error "no match" }
@@ -699,9 +699,9 @@ seven sink_3_347(volatile A&&); // { dg-message "seven sink_3_347|no know
int test3_347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_347(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 705 }
sink_3_347(cv_source()); // { dg-error "no match" }
@@ -716,9 +716,9 @@ six sink_3_356(const A&&); // { dg-message "six sink_3_356|no known
int test3_356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_356(ca); // { dg-error "lvalue" }
sink_3_356(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 723 }
@@ -736,9 +736,9 @@ seven sink_3_357(volatile A&&); // { dg-message "seven sink_3_357|no know
int test3_357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_357(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 742 }
sink_3_357(cva); // { dg-error "no match" }
@@ -757,9 +757,9 @@ eight sink_3_358(const volatile A&&); // { dg-message "" }
int test3_358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_358(ca); // { dg-error "lvalue" }
sink_3_358(cva); // { dg-error "lvalue" }
return 0;
@@ -772,9 +772,9 @@ seven sink_3_367(volatile A&&); // { dg-message "seven sink_3_367|no know
int test3_367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_367(ca); // { dg-error "lvalue" }
sink_3_367(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 779 }
@@ -792,9 +792,9 @@ eight sink_3_368(const volatile A&&); // { dg-message "" }
int test3_368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_368(ca); // { dg-error "lvalue" }
sink_3_368(cva); // { dg-error "lvalue" }
return 0;
@@ -807,9 +807,9 @@ eight sink_3_378(const volatile A&&); // { dg-message "" }
int test3_378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_378(ca); // { dg-error "lvalue" }
sink_3_378(cva); // { dg-error "lvalue" }
return 0;
@@ -822,9 +822,9 @@ six sink_3_456(const A&&); // { dg-message "note" }
int test3_456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 828 }
sink_3_456(cv_source()); // { dg-error "no match" }
@@ -839,9 +839,9 @@ seven sink_3_457(volatile A&&); // { dg-message "note" }
int test3_457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 845 }
sink_3_457(cv_source()); // { dg-error "no match" }
@@ -856,9 +856,9 @@ seven sink_3_467(volatile A&&); // { dg-message "note" }
int test3_467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 862 }
sink_3_467(cv_source()); // { dg-error "no match" }
@@ -873,9 +873,9 @@ seven sink_3_567(volatile A&&); // { dg-message "seven sink_3_567|no know
int test3_567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_567(a); // { dg-error "lvalue" }
sink_3_567(ca); // { dg-error "lvalue" }
sink_3_567(va); // { dg-error "lvalue" }
@@ -893,9 +893,9 @@ eight sink_3_568(const volatile A&&); // { dg-message "" }
int test3_568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_568(a); // { dg-error "lvalue" }
sink_3_568(ca); // { dg-error "lvalue" }
sink_3_568(va); // { dg-error "lvalue" }
@@ -910,9 +910,9 @@ eight sink_3_578(const volatile A&&); // { dg-message "" }
int test3_578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_578(a); // { dg-error "lvalue" }
sink_3_578(ca); // { dg-error "lvalue" }
sink_3_578(va); // { dg-error "lvalue" }
@@ -927,9 +927,9 @@ eight sink_3_678(const volatile A&&); // { dg-message "eight sink_3_678|no know
int test3_678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 933 }
sink_3_678(ca); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv4n.C b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
index daff3079851..076e9a0488e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv4n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -38,9 +38,9 @@ four sink_4_1234(const volatile A&); // { dg-message "note" }
int test4_1234()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1234(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 44 }
sink_4_1234(cv_source()); // { dg-error "no match" }
@@ -56,9 +56,9 @@ five sink_4_1235( A&&); // { dg-message "note" }
int test4_1235()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1235(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 62 }
sink_4_1235(v_source()); // { dg-error "no match" }
@@ -76,9 +76,9 @@ six sink_4_1236(const A&&); // { dg-message "note" }
int test4_1236()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1236(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 82 }
sink_4_1236(v_source()); // { dg-error "no match" }
@@ -96,9 +96,9 @@ seven sink_4_1237(volatile A&&); // { dg-message "note" }
int test4_1237()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1237(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 102 }
sink_4_1237(cv_source()); // { dg-error "no match" }
@@ -114,9 +114,9 @@ eight sink_4_1238(const volatile A&&); // { dg-message "" }
int test4_1238()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1238(cva); // { dg-error "lvalue" }
return 0;
}
@@ -129,9 +129,9 @@ five sink_4_1245( A&&); // { dg-message "note" }
int test4_1245()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1245(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 135 }
sink_4_1245(cv_source()); // { dg-error "no match" }
@@ -147,9 +147,9 @@ six sink_4_1246(const A&&); // { dg-message "note" }
int test4_1246()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1246(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 153 }
sink_4_1246(cv_source()); // { dg-error "no match" }
@@ -165,9 +165,9 @@ seven sink_4_1247(volatile A&&); // { dg-message "note" }
int test4_1247()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1247(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 171 }
return 0;
@@ -181,9 +181,9 @@ six sink_4_1256(const A&&); // { dg-message "note" }
int test4_1256()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1256(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 187 }
sink_4_1256(cva); // { dg-error "no match" }
@@ -203,9 +203,9 @@ seven sink_4_1257(volatile A&&); // { dg-message "" }
int test4_1257()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1257(va); // { dg-error "lvalue" }
sink_4_1257(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 210 }
@@ -222,9 +222,9 @@ eight sink_4_1258(const volatile A&&); // { dg-message "" }
int test4_1258()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1258(va); // { dg-error "lvalue" }
sink_4_1258(cva); // { dg-error "lvalue" }
return 0;
@@ -238,9 +238,9 @@ seven sink_4_1267(volatile A&&); // { dg-message "" }
int test4_1267()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1267(va); // { dg-error "lvalue" }
sink_4_1267(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 245 }
@@ -259,9 +259,9 @@ eight sink_4_1268(const volatile A&&); // { dg-message "" }
int test4_1268()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1268(va); // { dg-error "lvalue" }
sink_4_1268(cva); // { dg-error "lvalue" }
return 0;
@@ -275,9 +275,9 @@ eight sink_4_1278(const volatile A&&); // { dg-message "" }
int test4_1278()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1278(va); // { dg-error "lvalue" }
sink_4_1278(cva); // { dg-error "lvalue" }
return 0;
@@ -291,9 +291,9 @@ five sink_4_1345( A&&); // { dg-message "note" }
int test4_1345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1345(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 297 }
sink_4_1345(v_source()); // { dg-error "no match" }
@@ -311,9 +311,9 @@ six sink_4_1346(const A&&); // { dg-message "note" }
int test4_1346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1346(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 317 }
sink_4_1346(cv_source()); // { dg-error "no match" }
@@ -329,9 +329,9 @@ seven sink_4_1347(volatile A&&); // { dg-message "note" }
int test4_1347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1347(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 335 }
sink_4_1347(cv_source()); // { dg-error "no match" }
@@ -347,9 +347,9 @@ six sink_4_1356(const A&&); // { dg-message "" }
int test4_1356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1356(ca); // { dg-error "lvalue" }
sink_4_1356(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 354 }
@@ -368,9 +368,9 @@ seven sink_4_1357(volatile A&&); // { dg-message "note" }
int test4_1357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1357(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 374 }
sink_4_1357(cva); // { dg-error "no match" }
@@ -390,9 +390,9 @@ eight sink_4_1358(const volatile A&&); // { dg-message "" }
int test4_1358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1358(ca); // { dg-error "lvalue" }
sink_4_1358(cva); // { dg-error "lvalue" }
return 0;
@@ -406,9 +406,9 @@ seven sink_4_1367(volatile A&&); // { dg-message "note" }
int test4_1367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1367(ca); // { dg-error "lvalue" }
sink_4_1367(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 413 }
@@ -427,9 +427,9 @@ eight sink_4_1368(const volatile A&&); // { dg-message "" }
int test4_1368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1368(ca); // { dg-error "lvalue" }
sink_4_1368(cva); // { dg-error "lvalue" }
return 0;
@@ -443,9 +443,9 @@ eight sink_4_1378(const volatile A&&); // { dg-message "" }
int test4_1378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1378(ca); // { dg-error "lvalue" }
sink_4_1378(cva); // { dg-error "lvalue" }
return 0;
@@ -459,9 +459,9 @@ six sink_4_1456(const A&&); // { dg-message "note" }
int test4_1456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 465 }
sink_4_1456(cv_source()); // { dg-error "no match" }
@@ -477,9 +477,9 @@ seven sink_4_1457(volatile A&&); // { dg-message "note" }
int test4_1457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 483 }
sink_4_1457(cv_source()); // { dg-error "no match" }
@@ -495,9 +495,9 @@ seven sink_4_1467(volatile A&&); // { dg-message "note" }
int test4_1467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 501 }
sink_4_1467(cv_source()); // { dg-error "no match" }
@@ -513,9 +513,9 @@ seven sink_4_1567(volatile A&&); // { dg-message "" }
int test4_1567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1567(ca); // { dg-error "lvalue" }
sink_4_1567(va); // { dg-error "lvalue" }
sink_4_1567(cva); // { dg-error "no match" }
@@ -533,9 +533,9 @@ eight sink_4_1568(const volatile A&&); // { dg-message "" }
int test4_1568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1568(ca); // { dg-error "lvalue" }
sink_4_1568(va); // { dg-error "lvalue" }
sink_4_1568(cva); // { dg-error "lvalue" }
@@ -550,9 +550,9 @@ eight sink_4_1578(const volatile A&&); // { dg-message "" }
int test4_1578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1578(ca); // { dg-error "lvalue" }
sink_4_1578(va); // { dg-error "lvalue" }
sink_4_1578(cva); // { dg-error "lvalue" }
@@ -567,9 +567,9 @@ eight sink_4_1678(const volatile A&&); // { dg-message "" }
int test4_1678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1678(ca); // { dg-error "lvalue" }
sink_4_1678(va); // { dg-error "lvalue" }
sink_4_1678(cva); // { dg-error "lvalue" }
@@ -586,9 +586,9 @@ five sink_4_2345( A&&); // { dg-message "note" }
int test4_2345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2345(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 592 }
sink_4_2345(v_source()); // { dg-error "no match" }
@@ -606,9 +606,9 @@ six sink_4_2346(const A&&); // { dg-message "note" }
int test4_2346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2346(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 612 }
sink_4_2346(v_source()); // { dg-error "no match" }
@@ -626,9 +626,9 @@ seven sink_4_2347(volatile A&&); // { dg-message "note" }
int test4_2347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2347(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 632 }
sink_4_2347(cv_source()); // { dg-error "no match" }
@@ -644,9 +644,9 @@ eight sink_4_2348(const volatile A&&); // { dg-message "note" }
int test4_2348()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2348(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 650 }
return 0;
@@ -660,9 +660,9 @@ six sink_4_2356(const A&&); // { dg-message "note" }
int test4_2356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2356(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 666 }
sink_4_2356(cva); // { dg-error "no match" }
@@ -682,9 +682,9 @@ seven sink_4_2357(volatile A&&); // { dg-message "note" }
int test4_2357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2357(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 688 }
sink_4_2357(cva); // { dg-error "no match" }
@@ -702,9 +702,9 @@ eight sink_4_2358(const volatile A&&); // { dg-message "" }
int test4_2358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2358(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 708 }
sink_4_2358(cva); // { dg-error "lvalue" }
@@ -719,9 +719,9 @@ seven sink_4_2367(volatile A&&); // { dg-message "note" }
int test4_2367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2367(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 725 }
sink_4_2367(cva); // { dg-error "no match" }
@@ -741,9 +741,9 @@ eight sink_4_2368(const volatile A&&); // { dg-message "" }
int test4_2368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2368(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 747 }
sink_4_2368(cva); // { dg-error "lvalue" }
@@ -758,9 +758,9 @@ eight sink_4_2378(const volatile A&&); // { dg-message "" }
int test4_2378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2378(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 764 }
sink_4_2378(cva); // { dg-error "lvalue" }
@@ -775,9 +775,9 @@ six sink_4_2456(const A&&); // { dg-message "note" }
int test4_2456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 781 }
sink_4_2456(cv_source()); // { dg-error "no match" }
@@ -793,9 +793,9 @@ seven sink_4_2457(volatile A&&); // { dg-message "note" }
int test4_2457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2457(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 799 }
return 0;
@@ -809,9 +809,9 @@ seven sink_4_2467(volatile A&&); // { dg-message "note" }
int test4_2467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 815 }
sink_4_2467(cv_source()); // { dg-error "no match" }
@@ -827,9 +827,9 @@ seven sink_4_2567(volatile A&&); // { dg-message "" }
int test4_2567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2567(va); // { dg-error "lvalue" }
sink_4_2567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 834 }
@@ -846,9 +846,9 @@ eight sink_4_2568(const volatile A&&); // { dg-message "" }
int test4_2568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2568(va); // { dg-error "lvalue" }
sink_4_2568(cva); // { dg-error "lvalue" }
return 0;
@@ -862,9 +862,9 @@ eight sink_4_2578(const volatile A&&); // { dg-message "" }
int test4_2578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2578(va); // { dg-error "lvalue" }
sink_4_2578(cva); // { dg-error "lvalue" }
return 0;
@@ -878,9 +878,9 @@ eight sink_4_2678(const volatile A&&); // { dg-message "" }
int test4_2678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2678(va); // { dg-error "lvalue" }
sink_4_2678(cva); // { dg-error "lvalue" }
sink_4_2678(source()); // { dg-error "ambiguous" }
@@ -896,9 +896,9 @@ six sink_4_3456(const A&&); // { dg-message "note" }
int test4_3456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 902 }
sink_4_3456(cv_source()); // { dg-error "no match" }
@@ -914,9 +914,9 @@ seven sink_4_3457(volatile A&&); // { dg-message "note" }
int test4_3457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 920 }
sink_4_3457(cv_source()); // { dg-error "no match" }
@@ -932,9 +932,9 @@ seven sink_4_3467(volatile A&&); // { dg-message "note" }
int test4_3467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 938 }
sink_4_3467(cv_source()); // { dg-error "no match" }
@@ -950,9 +950,9 @@ seven sink_4_3567(volatile A&&); // { dg-message "note" }
int test4_3567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3567(ca); // { dg-error "lvalue" }
sink_4_3567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 957 }
@@ -969,9 +969,9 @@ eight sink_4_3568(const volatile A&&); // { dg-message "" }
int test4_3568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3568(ca); // { dg-error "lvalue" }
sink_4_3568(cva); // { dg-error "lvalue" }
return 0;
@@ -985,9 +985,9 @@ eight sink_4_3578(const volatile A&&); // { dg-message "" }
int test4_3578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3578(ca); // { dg-error "lvalue" }
sink_4_3578(cva); // { dg-error "lvalue" }
return 0;
@@ -1001,9 +1001,9 @@ eight sink_4_3678(const volatile A&&); // { dg-message "" }
int test4_3678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3678(ca); // { dg-error "lvalue" }
sink_4_3678(cva); // { dg-error "lvalue" }
sink_4_3678(source()); // { dg-error "ambiguous" }
@@ -1019,9 +1019,9 @@ seven sink_4_4567(volatile A&&); // { dg-message "note" }
int test4_4567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_4567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 1025 }
return 0;
@@ -1035,9 +1035,9 @@ eight sink_4_4678(const volatile A&&); // { dg-message "note" }
int test4_4678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_4678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 1041 }
return 0;
@@ -1051,9 +1051,9 @@ eight sink_4_5678(const volatile A&&); // { dg-message "" }
int test4_5678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_5678(a); // { dg-error "lvalue" }
sink_4_5678(ca); // { dg-error "lvalue" }
sink_4_5678(va); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv5n.C b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
index 660a68986a0..d9b8cd23988 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv5n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -39,9 +39,9 @@ five sink_5_12345( A&&); // { dg-message "note" }
int test5_12345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12345(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 45 }
sink_5_12345(cv_source()); // { dg-error "no match" }
@@ -58,9 +58,9 @@ six sink_5_12346(const A&&); // { dg-message "note" }
int test5_12346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12346(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 64 }
sink_5_12346(cv_source()); // { dg-error "no match" }
@@ -77,9 +77,9 @@ seven sink_5_12347(volatile A&&); // { dg-message "note" }
int test5_12347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12347(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 83 }
return 0;
@@ -94,9 +94,9 @@ six sink_5_12356(const A&&); // { dg-message "note" }
int test5_12356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12356(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 100 }
sink_5_12356(v_source()); // { dg-error "no match" }
@@ -115,9 +115,9 @@ seven sink_5_12357(volatile A&&); // { dg-message "note" }
int test5_12357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12357(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 121 }
sink_5_12357(cv_source()); // { dg-error "no match" }
@@ -134,9 +134,9 @@ eight sink_5_12358(const volatile A&&); // { dg-message "" }
int test5_12358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12358(cva); // { dg-error "lvalue" }
return 0;
}
@@ -150,9 +150,9 @@ seven sink_5_12367(volatile A&&); // { dg-message "note" }
int test5_12367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12367(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 156 }
sink_5_12367(source()); // { dg-error "ambiguous" }
@@ -171,9 +171,9 @@ eight sink_5_12368(const volatile A&&); // { dg-message "" }
int test5_12368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12368(cva); // { dg-error "lvalue" }
return 0;
}
@@ -187,9 +187,9 @@ eight sink_5_12378(const volatile A&&); // { dg-message "" }
int test5_12378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12378(cva); // { dg-error "lvalue" }
return 0;
}
@@ -203,9 +203,9 @@ six sink_5_12456(const A&&); // { dg-message "note" }
int test5_12456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 209 }
sink_5_12456(cv_source()); // { dg-error "no match" }
@@ -222,9 +222,9 @@ seven sink_5_12457(volatile A&&); // { dg-message "note" }
int test5_12457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12457(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 228 }
return 0;
@@ -239,9 +239,9 @@ seven sink_5_12467(volatile A&&); // { dg-message "note" }
int test5_12467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 245 }
sink_5_12467(cv_source()); // { dg-error "no match" }
@@ -258,9 +258,9 @@ seven sink_5_12567(volatile A&&); // { dg-message "" }
int test5_12567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12567(va); // { dg-error "lvalue" }
sink_5_12567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 265 }
@@ -278,9 +278,9 @@ eight sink_5_12568(const volatile A&&); // { dg-message "" }
int test5_12568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12568(va); // { dg-error "lvalue" }
sink_5_12568(cva); // { dg-error "lvalue" }
return 0;
@@ -295,9 +295,9 @@ eight sink_5_12578(const volatile A&&); // { dg-message "" }
int test5_12578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12578(va); // { dg-error "lvalue" }
sink_5_12578(cva); // { dg-error "lvalue" }
return 0;
@@ -312,9 +312,9 @@ eight sink_5_12678(const volatile A&&); // { dg-message "" }
int test5_12678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12678(va); // { dg-error "lvalue" }
sink_5_12678(cva); // { dg-error "lvalue" }
sink_5_12678(source()); // { dg-error "ambiguous" }
@@ -331,9 +331,9 @@ six sink_5_13456(const A&&); // { dg-message "note" }
int test5_13456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 337 }
sink_5_13456(cv_source()); // { dg-error "no match" }
@@ -350,9 +350,9 @@ seven sink_5_13457(volatile A&&); // { dg-message "note" }
int test5_13457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 356 }
sink_5_13457(cv_source()); // { dg-error "no match" }
@@ -369,9 +369,9 @@ seven sink_5_13467(volatile A&&); // { dg-message "note" }
int test5_13467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 375 }
sink_5_13467(cv_source()); // { dg-error "no match" }
@@ -388,9 +388,9 @@ seven sink_5_13567(volatile A&&); // { dg-message "note" }
int test5_13567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13567(ca); // { dg-error "lvalue" }
sink_5_13567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 395 }
@@ -408,9 +408,9 @@ eight sink_5_13568(const volatile A&&); // { dg-message "" }
int test5_13568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13568(ca); // { dg-error "lvalue" }
sink_5_13568(cva); // { dg-error "lvalue" }
return 0;
@@ -425,9 +425,9 @@ eight sink_5_13578(const volatile A&&); // { dg-message "" }
int test5_13578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13578(ca); // { dg-error "lvalue" }
sink_5_13578(cva); // { dg-error "lvalue" }
return 0;
@@ -442,9 +442,9 @@ eight sink_5_13678(const volatile A&&); // { dg-message "" }
int test5_13678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13678(ca); // { dg-error "lvalue" }
sink_5_13678(cva); // { dg-error "lvalue" }
sink_5_13678(source()); // { dg-error "ambiguous" }
@@ -461,9 +461,9 @@ seven sink_5_14567(volatile A&&); // { dg-message "note" }
int test5_14567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_14567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 467 }
return 0;
@@ -478,9 +478,9 @@ eight sink_5_14678(const volatile A&&); // { dg-message "note" }
int test5_14678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_14678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 484 }
return 0;
@@ -495,9 +495,9 @@ eight sink_5_15678(const volatile A&&); // { dg-message "" }
int test5_15678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_15678(ca); // { dg-error "lvalue" }
sink_5_15678(va); // { dg-error "lvalue" }
sink_5_15678(cva); // { dg-error "lvalue" }
@@ -513,9 +513,9 @@ six sink_5_23456(const A&&); // { dg-message "note" }
int test5_23456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23456(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 519 }
sink_5_23456(v_source()); // { dg-error "no match" }
@@ -534,9 +534,9 @@ seven sink_5_23457(volatile A&&); // { dg-message "note" }
int test5_23457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23457(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 540 }
sink_5_23457(cv_source()); // { dg-error "no match" }
@@ -553,9 +553,9 @@ eight sink_5_23458(const volatile A&&); // { dg-message "note" }
int test5_23458()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23458(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 559 }
return 0;
@@ -570,9 +570,9 @@ seven sink_5_23467(volatile A&&); // { dg-message "note" }
int test5_23467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23467(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 576 }
sink_5_23467(source()); // { dg-error "ambiguous" }
@@ -591,9 +591,9 @@ eight sink_5_23468(const volatile A&&); // { dg-message "note" }
int test5_23468()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23468(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 597 }
return 0;
@@ -608,9 +608,9 @@ eight sink_5_23478(const volatile A&&); // { dg-message "note" }
int test5_23478()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23478(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 614 }
return 0;
@@ -625,9 +625,9 @@ seven sink_5_23567(volatile A&&); // { dg-message "note" }
int test5_23567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23567(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 631 }
sink_5_23567(cva); // { dg-error "no match" }
@@ -646,9 +646,9 @@ eight sink_5_23568(const volatile A&&); // { dg-message "" }
int test5_23568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23568(cva); // { dg-error "lvalue" }
sink_5_23568(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 653 }
@@ -664,9 +664,9 @@ eight sink_5_23578(const volatile A&&); // { dg-message "" }
int test5_23578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23578(cva); // { dg-error "lvalue" }
sink_5_23578(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 671 }
@@ -682,9 +682,9 @@ eight sink_5_23678(const volatile A&&); // { dg-message "" }
int test5_23678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 688 }
sink_5_23678(cva); // { dg-error "lvalue" }
@@ -702,9 +702,9 @@ seven sink_5_24567(volatile A&&); // { dg-message "note" }
int test5_24567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_24567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 708 }
return 0;
@@ -719,9 +719,9 @@ eight sink_5_24678(const volatile A&&); // { dg-message "note" }
int test5_24678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_24678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 725 }
return 0;
@@ -736,9 +736,9 @@ eight sink_5_25678(const volatile A&&); // { dg-message "" }
int test5_25678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_25678(va); // { dg-error "lvalue" }
sink_5_25678(cva); // { dg-error "lvalue" }
return 0;
@@ -753,9 +753,9 @@ seven sink_5_34567(volatile A&&); // { dg-message "note" }
int test5_34567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_34567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 759 }
return 0;
@@ -770,9 +770,9 @@ eight sink_5_34678(const volatile A&&); // { dg-message "note" }
int test5_34678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_34678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 776 }
return 0;
@@ -787,9 +787,9 @@ eight sink_5_35678(const volatile A&&); // { dg-message "" }
int test5_35678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_35678(ca); // { dg-error "lvalue" }
sink_5_35678(cva); // { dg-error "lvalue" }
return 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv6n.C b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
index d0fdbb7e509..fbc932de1ef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv6n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -40,9 +40,9 @@ six sink_6_123456(const A&&); // { dg-message "note" }
int test6_123456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 46 }
sink_6_123456(cv_source()); // { dg-error "no match" }
@@ -60,9 +60,9 @@ seven sink_6_123457(volatile A&&); // { dg-message "note" }
int test6_123457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123457(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 66 }
return 0;
@@ -78,9 +78,9 @@ eight sink_6_235678(const volatile A&&); // { dg-message "" }
int test6_235678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_235678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 84 }
sink_6_235678(cva); // { dg-error "lvalue" }
@@ -97,9 +97,9 @@ eight sink_6_234678(const volatile A&&); // { dg-message "note" }
int test6_234678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 103 }
sink_6_234678(source()); // { dg-error "ambiguous" }
@@ -117,9 +117,9 @@ eight sink_6_234578(const volatile A&&); // { dg-message "note" }
int test6_234578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234578(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 123 }
return 0;
@@ -135,9 +135,9 @@ eight sink_6_234568(const volatile A&&); // { dg-message "note" }
int test6_234568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234568(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 141 }
return 0;
@@ -153,9 +153,9 @@ seven sink_6_234567(volatile A&&); // { dg-message "note" }
int test6_234567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234567(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 159 }
sink_6_234567(cv_source()); // { dg-error "no match" }
@@ -173,9 +173,9 @@ eight sink_6_134678(const volatile A&&); // { dg-message "note" }
int test6_134678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_134678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 179 }
return 0;
@@ -191,9 +191,9 @@ eight sink_6_124678(const volatile A&&); // { dg-message "note" }
int test6_124678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_124678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 197 }
return 0;
@@ -209,9 +209,9 @@ eight sink_6_123678(const volatile A&&); // { dg-message "" }
int test6_123678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123678(cva); // { dg-error "lvalue" }
sink_6_123678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 216 }
@@ -228,9 +228,9 @@ seven sink_6_123567(volatile A&&); // { dg-message "note" }
int test6_123567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 234 }
sink_6_123567(cv_source()); // { dg-error "no match" }
@@ -248,9 +248,9 @@ eight sink_6_123568(const volatile A&&); // { dg-message "" }
int test6_123568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123568(cva); // { dg-error "lvalue" }
return 0;
}
@@ -265,9 +265,9 @@ eight sink_6_123578(const volatile A&&); // { dg-message "" }
int test6_123578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123578(cva); // { dg-error "lvalue" }
return 0;
}
@@ -282,9 +282,9 @@ seven sink_6_123467(volatile A&&); // { dg-message "note" }
int test6_123467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 288 }
sink_6_123467(cv_source()); // { dg-error "no match" }
@@ -302,9 +302,9 @@ seven sink_6_124567(volatile A&&); // { dg-message "note" }
int test6_124567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_124567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 308 }
return 0;
@@ -320,9 +320,9 @@ eight sink_6_125678(const volatile A&&); // { dg-message "" }
int test6_125678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_125678(va); // { dg-error "lvalue" }
sink_6_125678(cva); // { dg-error "lvalue" }
return 0;
@@ -338,9 +338,9 @@ seven sink_6_134567(volatile A&&); // { dg-message "note" }
int test6_134567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_134567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 344 }
return 0;
@@ -356,9 +356,9 @@ eight sink_6_135678(const volatile A&&); // { dg-message "" }
int test6_135678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_135678(ca); // { dg-error "lvalue" }
sink_6_135678(cva); // { dg-error "lvalue" }
return 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv7n.C b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
index 6071e056813..206cc79bb14 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv7n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -41,9 +41,9 @@ seven sink_7_1234567(volatile A&&); // { dg-message "note" }
int test7_1234567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_1234567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 47 }
return 0;
@@ -60,9 +60,9 @@ eight sink_7_1235678(const volatile A&&); // { dg-message "" }
int test7_1235678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_1235678(cva); // { dg-error "lvalue" }
return 0;
}
@@ -78,9 +78,9 @@ eight sink_7_2345678(const volatile A&&); // { dg-message "note" }
int test7_2345678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_2345678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 84 }
return 0;
@@ -97,9 +97,9 @@ eight sink_7_1234678(const volatile A&&); // { dg-message "note" }
int test7_1234678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_1234678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 103 }
return 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C
new file mode 100644
index 00000000000..a097f43d218
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C
@@ -0,0 +1,11 @@
+// { dg-options -std=c++0x }
+
+template<class T, class U> struct A { };
+template<class... T, class ... U> void f( A<T,U>... p);
+
+void g() {
+ f<int>(
+ A<int,unsigned>(),
+ A<short,unsigned short>()
+ );
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C
new file mode 100644
index 00000000000..a64d7971c6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+template <class... T>
+void f(T..., int, T...) { }
+
+int main()
+{
+ f(0);
+ f<int>(0,0,0);
+ f<int,int>(0,0,0,0,0);
+ f(0,0,0); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C
index 66387b23c47..66d24a7efe3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C
@@ -20,6 +20,6 @@ struct call_sum {
int main() {
// This shouldn't be an error; this is bug 35722.
- reverse<call_sum>(1,2); // { dg-bogus "no match" "" { xfail *-*-* } }
- // { dg-bogus "sorry, unimplemented" "candidate explanation" { xfail *-*-* } 6 }
+ reverse<call_sum>(1,2); // { dg-bogus "no match" "" }
+ // { dg-bogus "sorry, unimplemented" "candidate explanation" { target *-*-* } 6 }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic117.C b/gcc/testsuite/g++.dg/cpp0x/variadic117.C
new file mode 100644
index 00000000000..22f2fc5ae2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic117.C
@@ -0,0 +1,11 @@
+// { dg-options -std=c++0x }
+
+template <class T> struct A { typedef T type; };
+
+template <template <class...> class T, class... U>
+void f(typename T<U...>::type);
+
+int main()
+{
+ f<A,int>(42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic118.C b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
new file mode 100644
index 00000000000..43bf9bab213
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
@@ -0,0 +1,11 @@
+// This should fail deduction, before it produces a candidate.
+// { dg-options -std=c++0x }
+
+template <class... T>
+void f(T... ts); // { dg-message "deduction" }
+
+struct B { };
+int main()
+{
+ f<int>(B(), 1); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic35.C b/gcc/testsuite/g++.dg/cpp0x/variadic35.C
index 1f21976e864..666a1f5d039 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic35.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic35.C
@@ -5,6 +5,5 @@ void get_ith(const Args&... args); // { dg-message "note" }
void f()
{
get_ith<1, float>(1, 2.0, 'x');
- get_ith<1, int, double, char, int>(1, 2.0, 'x'); // { dg-error "no matching function" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
+ get_ith<1, int, double, char, int>(1, 2.0, 'x'); // { dg-error "too few arguments" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic65.C b/gcc/testsuite/g++.dg/cpp0x/variadic65.C
index 1c815d1d90f..77be10676ae 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic65.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic65.C
@@ -5,4 +5,9 @@ template<typename T1 = unused, typename T2 = unused, typename T3 = unused,
struct tuple {};
template<typename... Args>
-void foo(tuple<Args...>) { } // { dg-bogus "cannot expand" "" { xfail *-*-* } }
+tuple<Args...> foo() { } // { dg-bogus "cannot expand" "" }
+
+int main()
+{
+ foo<int,int,int,int,int,int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic82.C b/gcc/testsuite/g++.dg/cpp0x/variadic82.C
index fb3ddb3c9b9..03aec80211d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic82.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic82.C
@@ -3,9 +3,9 @@
template<typename> struct A;
-template<typename... T> struct A<T*...> // { dg-bogus "cannot expand" "" { xfail *-*-* } }
+template<typename... T> struct A<T*...> // { dg-bogus "cannot expand" "" }
{
struct B;
};
-A<void*> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
+A<void*> a; // { dg-bogus "incomplete type" "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic83.C b/gcc/testsuite/g++.dg/cpp0x/variadic83.C
index 2613d625f09..c446e697420 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic83.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic83.C
@@ -3,6 +3,6 @@
template<typename> struct A;
-template<typename... T> struct A<T...> { }; // { dg-bogus "cannot expand" "" { xfail *-*-* } }
+template<typename... T> struct A<T...> { }; // { dg-bogus "cannot expand" "" }
-A<int> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
+A<int> a; // { dg-bogus "incomplete type" "" }
diff --git a/gcc/testsuite/g++.dg/ext/bases.C b/gcc/testsuite/g++.dg/ext/bases.C
new file mode 100644
index 00000000000..0582f72eb81
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/bases.C
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++0x -w" }
+// { dg-do run }
+
+#include<typeinfo>
+#include<cassert>
+
+// A simple typelist
+template<typename... _Elements> struct types {};
+
+// Simple bases implementation
+template<typename T> struct b {
+ typedef types<__bases(T)...> type;
+};
+
+// Simple direct_bases implementation
+template<typename T> struct db {
+ typedef types<__direct_bases(T)...> type;
+};
+
+template <class,class> struct assert_same_type;
+template <class T> struct assert_same_type<T,T> {};
+
+struct A {};
+struct C : virtual A {};
+struct D : public C {};
+struct B : D, virtual A {};
+struct E : C, virtual D, B {};
+struct F : A, B, E {};
+
+int main() {
+ assert_same_type<b<F>::type, types<A,C,D,A,C,D,B,C,C,D,B,E>>();
+ assert_same_type<db<F>::type, types<A,B,E>>();
+ assert_same_type<db<int>::type, types<>>();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C b/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
index 8cb1ce38f63..4ccc72b9e94 100644
--- a/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
+++ b/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
@@ -1,7 +1,7 @@
class A
{ };
-class B;
+class B; // { dg-error "forward declaration" }
union C
{ };
diff --git a/gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C b/gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C
new file mode 100644
index 00000000000..4704ff5dee1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C
@@ -0,0 +1,9 @@
+// PR c++/50732
+
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
diff --git a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
index 51cc80cd2ac..ecc5ec224b3 100644
--- a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
+++ b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
@@ -1,6 +1,6 @@
// PR c++/39475
-struct I;
+struct I; // { dg-error "forward declaration" }
struct C { };
bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" }
diff --git a/gcc/testsuite/g++.dg/inherit/error5.C b/gcc/testsuite/g++.dg/inherit/error5.C
new file mode 100644
index 00000000000..e38e106b14c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/error5.C
@@ -0,0 +1,14 @@
+// PR c++/48489
+
+struct Base{ };
+
+struct Concrete : Base
+{
+ void setValue();
+};
+
+int main()
+{
+ Concrete d;
+ d.Base::setValue(); // { dg-error "struct Base" }
+}
diff --git a/gcc/testsuite/g++.dg/init/ref20.C b/gcc/testsuite/g++.dg/init/ref20.C
new file mode 100644
index 00000000000..b64cb57e09d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/ref20.C
@@ -0,0 +1,8 @@
+// PR c++/50787
+// { dg-do run }
+
+int main() {
+ const int Ci = 0;
+ const int &rCi = Ci;
+ if (!(&Ci == &rCi)) __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/init/value9.C b/gcc/testsuite/g++.dg/init/value9.C
new file mode 100644
index 00000000000..4899bd81001
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/value9.C
@@ -0,0 +1,32 @@
+// PR c++/50793
+// { dg-do run }
+
+struct NonTrivial
+{
+ NonTrivial() { }
+};
+
+struct S
+{
+ NonTrivial nt;
+ int i;
+};
+
+int f(S s)
+{
+ s.i = 0xdeadbeef;
+ return s.i;
+}
+
+int g(S s = S())
+{
+ return s.i;
+}
+
+int main()
+{
+ f(S()); // make stack dirty
+
+ if ( g() )
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/init/vbase1.C b/gcc/testsuite/g++.dg/init/vbase1.C
new file mode 100644
index 00000000000..bbfd58f5c34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/vbase1.C
@@ -0,0 +1,39 @@
+// PR c++/50618
+// { dg-do run }
+
+struct Base
+{
+ const int text;
+ Base():text(1) {}
+ Base(int aText)
+ : text(aText) {}
+};
+struct SubA : public virtual Base
+{
+protected:
+ int x;
+public:
+ SubA(int aX)
+ : x(aX) {}
+};
+class SubB : public virtual Base
+{};
+struct Diamond : public SubA, public SubB
+{
+ Diamond(int text)
+ : Base(text), SubA(5), SubB() {}
+
+ void printText()
+ {
+ if(text != 2)
+ __builtin_abort();
+ if(x!=5)
+ __builtin_abort();
+ }
+};
+
+int main(int, char**)
+{
+ Diamond x(2);
+ x.printText();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using23.C b/gcc/testsuite/g++.dg/lookup/using23.C
new file mode 100644
index 00000000000..5dd8d8594b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using23.C
@@ -0,0 +1,13 @@
+// PR c++/50742
+
+typedef int A;
+
+void f(int i)
+{
+ switch (i)
+ {
+ case 0:
+ using ::A;
+ default:;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/other/final1.C b/gcc/testsuite/g++.dg/other/final1.C
index ffb30c3ec2c..3e02c252162 100644
--- a/gcc/testsuite/g++.dg/other/final1.C
+++ b/gcc/testsuite/g++.dg/other/final1.C
@@ -24,3 +24,4 @@ void fun(A* a, B* b)
/* { dg-final { scan-tree-dump-times "A::foo" 2 "original" } } */
/* { dg-final { scan-tree-dump-times "B::foo" 2 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/g++.dg/other/pr47218.C b/gcc/testsuite/g++.dg/other/pr47218.C
index f94e15742eb..57245c036b2 100644
--- a/gcc/testsuite/g++.dg/other/pr47218.C
+++ b/gcc/testsuite/g++.dg/other/pr47218.C
@@ -18,4 +18,4 @@ int main ()
return 0;
}
-// { dg-final cleanup-saved-temps }
+// { dg-final { cleanup-saved-temps } }
diff --git a/gcc/testsuite/g++.dg/overload/operator4.C b/gcc/testsuite/g++.dg/overload/operator4.C
new file mode 100644
index 00000000000..3ec1eb472dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/operator4.C
@@ -0,0 +1,14 @@
+// PR c++/38174
+
+struct VolatileIntPtr {
+ operator int volatile *();
+};
+
+struct ConstIntPtr {
+ operator int const *();
+};
+
+void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip) {
+ bool b1 = (vip == cip);
+ long p1 = vip - cip;
+}
diff --git a/gcc/testsuite/g++.dg/parse/error20.C b/gcc/testsuite/g++.dg/parse/error20.C
index d2f9353a7cc..6119df9b2d1 100644
--- a/gcc/testsuite/g++.dg/parse/error20.C
+++ b/gcc/testsuite/g++.dg/parse/error20.C
@@ -12,7 +12,7 @@ struct C {
};
int main() {
C c;
- A(c.p.i); // { dg-error "9:request for member 'i' in 'c.C::p', which is of non-class type 'B" }
+ A(c.p.i); // { dg-error "9:request for member 'i' in 'c.C::p', which is of pointer type 'B" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/parse/error41.C b/gcc/testsuite/g++.dg/parse/error41.C
new file mode 100644
index 00000000000..621a2e252ed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error41.C
@@ -0,0 +1,11 @@
+// PR c++/44524
+
+template<typename, typename>
+struct map
+{
+ bool empty();
+};
+
+int bar(map<int, float> *X) {
+ return X.empty(); // { dg-error "which is of pointer type 'map" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error42.C b/gcc/testsuite/g++.dg/parse/error42.C
new file mode 100644
index 00000000000..5e4c5bbdd2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error42.C
@@ -0,0 +1,4 @@
+// PR c++/13657
+
+class C { public: int (*f())(); int bar(); };
+int (*C::f())() { return C::bar; } // { dg-error "cannot convert 'C::bar'" }
diff --git a/gcc/testsuite/g++.dg/pr48660.C b/gcc/testsuite/g++.dg/pr48660.C
new file mode 100644
index 00000000000..37b61741ada
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr48660.C
@@ -0,0 +1,22 @@
+template<int N> struct val { char a[N]; };
+
+class Base
+{
+public:
+ virtual val<1> get1() const = 0;
+ virtual val<2> get2() const = 0;
+ virtual val<3> get3() const = 0;
+ virtual val<4> get4() const = 0;
+};
+
+class Derived : public virtual Base
+{
+public:
+ virtual val<1> get1() const { return foo->get1(); }
+ virtual val<2> get2() const { return foo->get2(); }
+ virtual val<3> get3() const { return foo->get3(); }
+ virtual val<4> get4() const { return foo->get4(); }
+ Base *foo;
+};
+
+Base* make() { return new Derived; }
diff --git a/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.exp b/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.exp
new file mode 100644
index 00000000000..f9e6475c054
--- /dev/null
+++ b/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.exp
@@ -0,0 +1,39 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+
+# Your run of the mill dg test, but verify that we have a working GDB first.
+
+load_lib g++-dg.exp
+load_lib gcc-simulate-thread.exp
+load_lib torture-options.exp
+
+dg-init
+torture-init
+set-torture-options [list \
+ { -O0 -g } \
+ { -O1 -g } \
+ { -O2 -g } \
+ { -O3 -g } \
+ { -Os -g } ]
+
+if [gdb-exists] {
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] ""
+ gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/simulate-thread/*.c]] ""
+}
+
+torture-finish
+dg-finish
diff --git a/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.gdb b/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.gdb
new file mode 100644
index 00000000000..eb081cb227c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.gdb
@@ -0,0 +1 @@
+source ../../gcc.dg/simulate-thread/simulate-thread.gdb
diff --git a/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.h b/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.h
new file mode 100644
index 00000000000..a07486bebe7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/simulate-thread/simulate-thread.h
@@ -0,0 +1 @@
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
diff --git a/gcc/testsuite/g++.dg/template/constant1.C b/gcc/testsuite/g++.dg/template/constant1.C
new file mode 100644
index 00000000000..a2c5a08d366
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/constant1.C
@@ -0,0 +1,13 @@
+// PR c++/49855
+
+extern void foo(int);
+
+template <class Key, class Value> void Basic() {
+ const int kT = 1.5e6; // <--- causes ICE
+ int size = kT*2/3;
+ do {
+ foo(size);
+ size = size * 0.5 - 1;
+ } while (size >= 0 );
+
+}
diff --git a/gcc/testsuite/g++.dg/template/constant2.C b/gcc/testsuite/g++.dg/template/constant2.C
new file mode 100644
index 00000000000..f71e4f56a22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/constant2.C
@@ -0,0 +1,22 @@
+// PR c++/49896
+
+template<class C>
+class test {
+ protected:
+ static const int versionConst = 0x80000000;
+ enum { versionEnum = versionConst };
+ public:
+ int getVersion();
+};
+
+template<class C>
+int test<C>::getVersion() {
+ return versionEnum;
+}
+
+class dummy_class {};
+
+int main() {
+ test<dummy_class> t;
+ return t.getVersion();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr50189.C b/gcc/testsuite/g++.dg/torture/pr50189.C
new file mode 100644
index 00000000000..06f1d3695c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr50189.C
@@ -0,0 +1,121 @@
+// { dg-do run }
+// { dg-options "-fstrict-enums" }
+
+extern "C" void abort (void);
+class CCUTILS_KeyedScalarLevelPosition
+{
+public:
+
+ typedef enum
+ {
+ UNINITED = 0,
+ AT_BEGIN = 1,
+ AT_END = 2,
+ AT_KEY = 3
+
+ } position_t;
+
+ bool is_init() const
+ { return(m_timestamp != UNINITED); }
+
+ bool is_at_begin() const
+ { return(m_timestamp == AT_BEGIN); }
+
+ position_t get_state() const
+ {
+ return((m_timestamp >= AT_KEY)
+ ? AT_KEY
+ : ((position_t)m_timestamp));
+ }
+
+ void set_at_begin()
+ { m_timestamp = AT_BEGIN; }
+
+ unsigned int get_index() const
+ { return(m_index); }
+
+ void set_pos(unsigned int a_index, unsigned int a_timestmap)
+ {
+ m_index = a_index;
+ m_timestamp = a_timestmap;
+ }
+
+ bool check_pos(unsigned int a_num_entries, unsigned int a_timestamp) const
+ {
+ if (get_state() != AT_KEY)
+ return(false);
+
+ if (m_timestamp != a_timestamp)
+ return(false);
+
+ return(m_index < a_num_entries);
+ }
+
+ void set_not_init()
+ { m_timestamp = 0; }
+
+private:
+
+ unsigned int m_timestamp;
+ unsigned int m_index;
+
+};
+
+class CCUTILS_KeyedScalarPosition
+{
+public:
+
+ CCUTILS_KeyedScalarLevelPosition m_L1;
+ CCUTILS_KeyedScalarLevelPosition m_L2;
+};
+
+class baz
+{
+public:
+ int *n[20];
+ unsigned int m_cur_array_len;
+ unsigned int m_timestamp;
+
+ unsigned int _get_timestamp() const
+ { return(m_timestamp); }
+
+ bool _check_L1_pos(const CCUTILS_KeyedScalarPosition &a_position) const
+ {
+ return(a_position.m_L1.check_pos(
+ m_cur_array_len, _get_timestamp()));
+ }
+
+ void *next (CCUTILS_KeyedScalarPosition &);
+};
+
+void * baz::next (CCUTILS_KeyedScalarPosition &a_position)
+{
+ if (a_position.m_L1.is_at_begin() || (!a_position.m_L1.is_init()))
+ {
+ a_position.m_L1.set_pos(0, _get_timestamp());
+ a_position.m_L2.set_at_begin();
+ }
+ else if (!_check_L1_pos(a_position))
+ return(0);
+
+ return n[a_position.m_L1.get_index ()];
+}
+
+int main (int, char **)
+{
+ baz obj;
+ CCUTILS_KeyedScalarPosition a_pos;
+ void *ret;
+ int n[5];
+
+ obj.n[0] = n;
+ obj.m_cur_array_len = 1;
+ obj.m_timestamp = 42;
+
+ a_pos.m_L1.set_pos (0, 42);
+
+ ret = obj.next (a_pos);
+ if (ret == 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/pr50698.cc b/gcc/testsuite/g++.dg/vect/pr50698.cc
new file mode 100644
index 00000000000..acb193665ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr50698.cc
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-require-effective-target vect_float }
+
+float mem[4096];
+const int N=1024;
+
+struct XYZ {
+ float * mem;
+ int n;
+ float * x() { return mem;}
+ float * y() { return x()+n;}
+ float * z() { return y()+n;}
+};
+
+inline
+void sum(float * x, float * y, float * z, int n) {
+ for (int i=0;i!=n; ++i)
+ x[i]=y[i]+z[i];
+}
+
+void sumS() {
+ XYZ xyz; xyz.mem=mem; xyz.n=N;
+ sum(xyz.x(),xyz.y(),xyz.z(),xyz.n);
+}
+
+// { dg-final { scan-tree-dump-not "run-time aliasing" "vect" } }
+// { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/g++.dg/warn/format5.C b/gcc/testsuite/g++.dg/warn/format5.C
new file mode 100644
index 00000000000..e219f881092
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/format5.C
@@ -0,0 +1,12 @@
+// PR c++/38980
+// { dg-options "-Wformat" }
+
+extern "C"
+int printf(const char *format, ...) __attribute__((format(printf, 1, 2) ));
+
+const char fmt1[] = "Hello, %s";
+
+void f()
+{
+ printf(fmt1, 3); // { dg-warning "expects argument" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/format6.C b/gcc/testsuite/g++.dg/warn/format6.C
new file mode 100644
index 00000000000..a74f8025d0e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/format6.C
@@ -0,0 +1,7 @@
+// PR c++/17212
+// { dg-options "-Wformat -Wno-format-zero-length" }
+
+void f()
+{
+ __builtin_printf("");
+}
diff --git a/gcc/testsuite/g++.dg/warn/format7.C b/gcc/testsuite/g++.dg/warn/format7.C
new file mode 100644
index 00000000000..6e84069eec5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/format7.C
@@ -0,0 +1,10 @@
+// PR c++/50757
+// { dg-options "-Wformat -Wno-nonnull" }
+
+extern void *f (void *__s) __attribute__ ((__nonnull__ (1)));
+
+int main()
+{
+ void* const s = 0;
+ f(s);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C b/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C
index b04f7e2657c..987c0445a67 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C
@@ -31,9 +31,9 @@ void A::foo ()
int (*ptr8) (short) = ns;
int (A::*ptr11) (int) = &A::single;
- int (A::*ptr12) (int) = A::single; // { dg-error "match" }
+ int (A::*ptr12) (int) = A::single; // { dg-error "cannot convert" }
int (A::*ptr13) (int) = &single; // { dg-error "pointer to member" }
- int (A::*ptr14) (int) = single; // { dg-error "match" }
+ int (A::*ptr14) (int) = single; // { dg-error "cannot convert" }
int (A::*ptr20) (int) = &(A::ns); // { dg-error "pointer to member" }
int (A::*ptr21) (int) = &(A::single); // { dg-error "pointer to member" }
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr49049.c b/gcc/testsuite/gcc.c-torture/compile/pr49049.c
new file mode 100644
index 00000000000..a24b2a41c75
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr49049.c
@@ -0,0 +1,28 @@
+__extension__ typedef unsigned long long int uint64_t;
+
+static int
+sub (int a, int b)
+{
+ return a - b;
+}
+
+static uint64_t
+add (uint64_t a, uint64_t b)
+{
+ return a + b;
+}
+
+int *ptr;
+
+int
+foo (uint64_t arg1, int *arg2)
+{
+ int j;
+ for (; j < 1; j++)
+ {
+ *arg2 |= sub ( sub (sub (j || 1 ^ 0x1, 1), arg1 < 0x1 <=
+ sub (1, *ptr & j)),
+ (sub ( j != 1 || sub (j && j, 1) >= 0,
+ add (!j > arg1, 0x35DLL))));
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr50565-1.c b/gcc/testsuite/gcc.c-torture/compile/pr50565-1.c
new file mode 100644
index 00000000000..cdaad294f1f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr50565-1.c
@@ -0,0 +1,4 @@
+struct s { char p[2]; };
+static struct s v;
+const int o0 = (int) ((void *) &v.p[0] - (void *) &v) + 0U;
+const int o1 = (int) ((void *) &v.p[0] - (void *) &v) + 1U;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr50565-2.c b/gcc/testsuite/gcc.c-torture/compile/pr50565-2.c
new file mode 100644
index 00000000000..2d30e88021f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr50565-2.c
@@ -0,0 +1,4 @@
+struct s { char p[2]; };
+static struct s v;
+const int o0 = (int) ((void *) &v.p[0] - (void *) &v) + 0;
+const int o1 = (int) ((void *) &v.p[0] - (void *) &v) + 1;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr50650.c b/gcc/testsuite/gcc.c-torture/compile/pr50650.c
new file mode 100644
index 00000000000..6c443e6475c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr50650.c
@@ -0,0 +1,10 @@
+/* PR tree-optimization/50650 */
+
+unsigned int
+foo (unsigned int x, unsigned int y)
+{
+ int i;
+ for (i = 8; i--; x <<= 1)
+ y ^= (x ^ y) & 0x80 ? 79U : 0U;
+ return y;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr49279.c b/gcc/testsuite/gcc.c-torture/execute/pr49279.c
new file mode 100644
index 00000000000..7f2c0d22129
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr49279.c
@@ -0,0 +1,35 @@
+/* PR tree-optimization/49279 */
+extern void abort (void);
+
+struct S { int a; int *__restrict p; };
+
+__attribute__((noinline, noclone))
+struct S *bar (struct S *p)
+{
+ struct S *r;
+ asm volatile ("" : "=r" (r) : "0" (p) : "memory");
+ return r;
+}
+
+__attribute__((noinline, noclone))
+int
+foo (int *p, int *q)
+{
+ struct S s, *t;
+ s.a = 1;
+ s.p = p;
+ t = bar (&s);
+ t->p = q;
+ s.p[0] = 0;
+ t->p[0] = 1;
+ return s.p[0];
+}
+
+int
+main ()
+{
+ int a, b;
+ if (foo (&a, &b) != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c b/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c
index 90eecb68a5d..8967d439406 100644
--- a/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c
@@ -39,17 +39,17 @@ int main (int argc, char *argv[]) {
int i;
i0 = (vector (4, INT)){argc, 1, 2, 10};
- i1 = (vector (4, INT)){0, 3, 2, (INT)-23};
+ i1 = (vector (4, INT)){0, 3, 2, (INT)-23};
test (4, i0, i1, ires, "%i");
#undef INT
-#define INT unsigned int
+#define INT unsigned int
vector (4, int) ures;
vector (4, INT) u0;
vector (4, INT) u1;
u0 = (vector (4, INT)){argc, 1, 2, 10};
- u1 = (vector (4, INT)){0, 3, 2, (INT)-23};
+ u1 = (vector (4, INT)){0, 3, 2, (INT)-23};
test (4, u0, u1, ures, "%u");
#undef INT
@@ -60,7 +60,7 @@ int main (int argc, char *argv[]) {
vector (8, short) sres;
s0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
- s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
+ s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
test (8, s0, s1, sres, "%i");
#undef SHORT
@@ -70,7 +70,7 @@ int main (int argc, char *argv[]) {
vector (8, short) usres;
us0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
- us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
+ us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
test (8, us0, us1, usres, "%u");
#undef SHORT
@@ -102,19 +102,19 @@ int main (int argc, char *argv[]) {
/* Float comparison. */
vector (4, float) f0;
vector (4, float) f1;
- vector (4, int) ifres;
+ __typeof (f0 == f1) ifres;
f0 = (vector (4, float)){(float)argc, 1., 2., 10.};
- f1 = (vector (4, float)){0., 3., 2., (float)-23};
+ f1 = (vector (4, float)){0., 3., 2., (float)-23};
test (4, f0, f1, ifres, "%f");
-
+
/* Double comparison. */
vector (2, double) d0;
vector (2, double) d1;
- vector (2, long long) idres;
+ __typeof (d0 == d1) idres;
d0 = (vector (2, double)){(double)argc, 10.};
- d1 = (vector (2, double)){0., (double)-23};
+ d1 = (vector (2, double)){0., (double)-23};
test (2, d0, d1, idres, "%f");
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-compare-2.x b/gcc/testsuite/gcc.c-torture/execute/vector-compare-2.x
new file mode 100644
index 00000000000..cb7b119b8cb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vector-compare-2.x
@@ -0,0 +1,2 @@
+set additional_flags "-Wno-psabi"
+return 0
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-16.inc b/gcc/testsuite/gcc.c-torture/execute/vshuf-16.inc
new file mode 100644
index 00000000000..68f2646d860
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-16.inc
@@ -0,0 +1,81 @@
+/* Test fragment for vectors with 16 elements. */
+
+#ifndef UNSUPPORTED
+
+struct S
+{
+ V in;
+ VI mask;
+ V out;
+};
+
+struct S tests[] = {
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ },
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
+ 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0xff },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ },
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },
+ { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+ },
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 },
+ { 1, 3, 5, 7, 9, 11, 13, 15, 2, 4, 6, 8, 10, 12, 14, 16 },
+ },
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+ { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+ },
+};
+
+struct S2
+{
+ V in1, in2;
+ VI mask;
+ V out;
+};
+
+struct S2 tests2[] = {
+ {
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
+ { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 },
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
+ },
+ {
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
+ { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 },
+ { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 },
+ { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 },
+ },
+ {
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
+ { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 },
+ { 7, 6, 5, 4, 16, 17, 18, 19, 31, 30, 29, 28, 3, 2, 1, 0 },
+ { 17, 16, 15, 14, 30, 31, 32, 33, 45, 44, 43, 42, 13, 12, 11, 10 },
+ },
+ {
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
+ { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 },
+ },
+ {
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
+ { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 },
+ { 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 },
+ { 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45 },
+ },
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-2.inc b/gcc/testsuite/gcc.c-torture/execute/vshuf-2.inc
new file mode 100644
index 00000000000..ef778e59418
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-2.inc
@@ -0,0 +1,38 @@
+/* Test fragment for vectors of 2 elements. */
+
+#ifndef UNSUPPORTED
+
+struct S
+{
+ V in;
+ VI mask;
+ V out;
+};
+
+struct S tests[] = {
+ { { A, B }, { 0, 1 }, { A, B } },
+ { { A, B }, { -16, -1 }, { A, B } },
+ { { A, B }, { 1, 0 }, { B, A } },
+ { { A, B }, { 0, 0 }, { A, A } },
+ { { X, Y }, { 1, 1 }, { Y, Y } },
+ { { X, Y }, { 1, 0 }, { Y, X } },
+};
+
+struct S2
+{
+ V in1, in2;
+ VI mask;
+ V out;
+};
+
+struct S2 tests2[] = {
+ { { A, B }, { X, Y }, { 0, 1 }, { A, B } },
+ { { A, B }, { X, Y }, { 2, 3 }, { X, Y } },
+ { { A, B }, { X, Y }, { 0, 2 }, { A, X } },
+ { { A, B }, { X, Y }, { 2, 1 }, { X, B } },
+ { { A, B }, { X, Y }, { 3, 0 }, { Y, A } },
+ { { A, B }, { X, Y }, { 0, 0 }, { A, A } },
+ { { A, B }, { X, Y }, { 3, 3 }, { Y, Y } },
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-4.inc b/gcc/testsuite/gcc.c-torture/execute/vshuf-4.inc
new file mode 100644
index 00000000000..d6e6e102295
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-4.inc
@@ -0,0 +1,39 @@
+/* Test fragment for vectors of 4 elements. */
+
+#ifndef UNSUPPORTED
+
+struct S
+{
+ V in;
+ VI mask;
+ V out;
+};
+
+struct S tests[] = {
+ { { A, B, C, D }, { 0, 1, 2, 3 }, { A, B, C, D }, },
+ { { A, B, C, D }, { 0+1*4, 1+2*4, 2+3*4, 3+4*4 }, { A, B, C, D } },
+ { { A, B, C, D }, { 3, 2, 1, 0 }, { D, C, B, A } },
+ { { A, B, C, D }, { 0, 3, 2, 1 }, { A, D, C, B } },
+ { { A, B, C, D }, { 0, 2, 1, 3 }, { A, C, B, D } },
+ { { W, X, Y, Z }, { 3, 1, 2, 0 }, { Z, X, Y, W } },
+ { { W, X, Y, Z }, { 0, 0, 0, 0 }, { W, W, W, W } },
+ { { W, X, Y, Z }, { 1, 2, 1, 2 }, { X, Y, X, Y } },
+};
+
+struct S2
+{
+ V in1, in2;
+ VI mask;
+ V out;
+};
+
+struct S2 tests2[] = {
+ { { A, B, C, D }, { W, X, Y, Z }, { 0, 1, 2, 3 }, { A, B, C, D } },
+ { { A, B, C, D }, { W, X, Y, Z }, { 4, 5, 6, 7 }, { W, X, Y, Z } },
+ { { A, B, C, D }, { W, X, Y, Z }, { 0, 4, 1, 5 }, { A, W, B, X } },
+ { { A, B, C, D }, { W, X, Y, Z }, { 0, 7, 4, 3 }, { A, Z, W, D } },
+ { { A, B, C, D }, { W, X, Y, Z }, { 0, 0, 0, 0 }, { A, A, A, A } },
+ { { A, B, C, D }, { W, X, Y, Z }, { 7, 7, 7, 7 }, { Z, Z, Z, Z } },
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-8.inc b/gcc/testsuite/gcc.c-torture/execute/vshuf-8.inc
new file mode 100644
index 00000000000..e6475226a11
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-8.inc
@@ -0,0 +1,101 @@
+/* Test fragment for vectors of 8 elements. */
+
+#ifndef UNSUPPORTED
+
+struct S
+{
+ V in;
+ VI mask;
+ V out;
+};
+
+struct S tests[] = {
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87 },
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { 7, 6, 5, 4, 3, 2, 1, 0 },
+ { H1, G1, F1, E1, D1, C1, B1, A1 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { 7, 0, 5, 3, 2, 4, 1, 6 },
+ { H1, A1, F1, D1, C1, E1, B1, G1 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { 0, 2, 1, 3, 4, 6, 5, 7 },
+ { A1, C1, B1, D1, E1, G1, F1, H1 },
+ },
+ {
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 3, 1, 2, 0, 7, 5, 6, 4 },
+ { D2, B2, C2, A2, H2, F2, G2, E2 },
+ },
+ {
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 0, 0, 0, 0 },
+ { A2, A2, A2, A2, A2, A2, A2, A2 },
+ },
+ {
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 1, 6, 1, 6, 1, 6, 1, 6 },
+ { B2, G2, B2, G2, B2, G2, B2, G2 },
+ }
+};
+
+struct S2
+{
+ V in1, in2;
+ VI mask;
+ V out;
+};
+
+struct S2 tests2[] = {
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 8, 9, 10, 11, 12, 13, 14, 15 },
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 0, 8, 1, 9, 2, 10, 3, 11 },
+ { A1, A2, B1, B2, C1, C2, D1, D2 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 0, 15, 4, 11, 12, 3, 7, 8 },
+ { A1, H2, E1, D2, E2, D1, H1, A2 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { A1, A1, A1, A1, A1, A1, A1, A1 },
+ },
+ {
+ { A1, B1, C1, D1, E1, F1, G1, H1 },
+ { A2, B2, C2, D2, E2, F2, G2, H2 },
+ { 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e, 0x8e },
+ { G2, G2, G2, G2, G2, G2, G2, G2 },
+ },
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-main.inc b/gcc/testsuite/gcc.c-torture/execute/vshuf-main.inc
new file mode 100644
index 00000000000..8487131b12d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-main.inc
@@ -0,0 +1,26 @@
+/* Driver fragment for __builtin_shuffle of any vector shape. */
+
+extern void abort(void);
+
+int main()
+{
+#ifndef UNSUPPORTED
+ int i;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i)
+ {
+ V r = __builtin_shuffle(tests[i].in, tests[i].mask);
+ if (__builtin_memcmp(&r, &tests[i].out, sizeof(V)) != 0)
+ abort();
+ }
+
+ for (i = 0; i < sizeof(tests2)/sizeof(tests2[0]); ++i)
+ {
+ V r = __builtin_shuffle(tests2[i].in1, tests2[i].in2, tests2[i].mask);
+ if (__builtin_memcmp(&r, &tests2[i].out, sizeof(V)) != 0)
+ abort();
+ }
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c
new file mode 100644
index 00000000000..98b329dbf91
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c
@@ -0,0 +1,5 @@
+typedef unsigned short V __attribute__((vector_size(32)));
+typedef V VI;
+
+#include "vshuf-16.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v16qi.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v16qi.c
new file mode 100644
index 00000000000..dcd1de1e646
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v16qi.c
@@ -0,0 +1,5 @@
+typedef unsigned char V __attribute__((vector_size(16)));
+typedef V VI;
+
+#include "vshuf-16.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v2df.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2df.c
new file mode 100644
index 00000000000..e88ec08ddf6
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2df.c
@@ -0,0 +1,15 @@
+#if __SIZEOF_DOUBLE__ == 8 && __SIZEOF_LONG_LONG__ == 8
+typedef double V __attribute__((vector_size(16)));
+typedef unsigned long long VI __attribute__((vector_size(16)));
+#else
+#define UNSUPPORTED
+#endif
+
+#define A 0.69314718055994530942
+#define B 2.7182818284590452354
+
+#define X 3.14159265358979323846
+#define Y 1.41421356237309504880
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v2di.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2di.c
new file mode 100644
index 00000000000..0985a0de02a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2di.c
@@ -0,0 +1,15 @@
+#if __SIZEOF_LONG_LONG__ == 8
+typedef unsigned long long V __attribute__((vector_size(16)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#define A 0x1112131415161718
+#define B 0x2122232425262728
+
+#define X 0xc1c2c3c4c5c6c7c8
+#define Y 0xd1d2d3d4d5d6d7d8
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v2sf.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2sf.c
new file mode 100644
index 00000000000..f9c40b22391
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2sf.c
@@ -0,0 +1,21 @@
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(8)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(8)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(8)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#define A 0.69314718055994530942f
+#define B 2.7182818284590452354f
+
+#define X 3.14159265358979323846f
+#define Y 1.41421356237309504880f
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v2si.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2si.c
new file mode 100644
index 00000000000..414743c892f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v2si.c
@@ -0,0 +1,18 @@
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(8)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(8)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#define A 0x11121314
+#define B 0x21222324
+
+#define X 0xd1d2d3d4
+#define Y 0xe1e2e3e4
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v4df.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4df.c
new file mode 100644
index 00000000000..c4030a7dbab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4df.c
@@ -0,0 +1,19 @@
+#if __SIZEOF_DOUBLE__ == 8 && __SIZEOF_LONG_LONG__ == 8
+typedef double V __attribute__((vector_size(32)));
+typedef unsigned long long VI __attribute__((vector_size(32)));
+#else
+#define UNSUPPORTED
+#endif
+
+#define A 0.69314718055994530942
+#define B 2.7182818284590452354
+#define C 2.30258509299404568402
+#define D 1.4426950408889634074
+
+#define W 0.31830988618379067154
+#define X 3.14159265358979323846
+#define Y 1.41421356237309504880
+#define Z 0.70710678118654752440
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v4di.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4di.c
new file mode 100644
index 00000000000..a84aebefb6d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4di.c
@@ -0,0 +1,19 @@
+#if __SIZEOF_LONG_LONG__ == 8
+typedef unsigned long long V __attribute__((vector_size(32)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#define A 0x1112131415161718
+#define B 0x2122232425262728
+#define C 0x3132333435363738
+#define D 0x4142434445464748
+
+#define W 0xc1c2c3c4c5c6c7c8
+#define X 0xd1d2d3d4d5d6d7d8
+#define Y 0xe1e2e3e4e5e6e7e8
+#define Z 0xf1f2f3f4f5f6f7f8
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v4hi.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4hi.c
new file mode 100644
index 00000000000..64a2bb4ac82
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4hi.c
@@ -0,0 +1,15 @@
+typedef unsigned short V __attribute__((vector_size(8)));
+typedef V VI;
+
+#define A 0x1112
+#define B 0x2122
+#define C 0x3132
+#define D 0x4142
+
+#define W 0xc1c2
+#define X 0xd1d2
+#define Y 0xe1e2
+#define Z 0xf1f2
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v4sf.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4sf.c
new file mode 100644
index 00000000000..283672560a3
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4sf.c
@@ -0,0 +1,25 @@
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(16)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(16)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(16)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#define A 0.69314718055994530942f
+#define B 2.7182818284590452354f
+#define C 2.30258509299404568402f
+#define D 1.4426950408889634074f
+
+#define W 0.31830988618379067154f
+#define X 3.14159265358979323846f
+#define Y 1.41421356237309504880f
+#define Z 0.70710678118654752440f
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v4si.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4si.c
new file mode 100644
index 00000000000..289ec1b5016
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v4si.c
@@ -0,0 +1,22 @@
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(16)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(16)));
+typedef V VI;
+#else
+# define UNSUPPORTED
+#endif
+
+#define A 0x11121314
+#define B 0x21222324
+#define C 0x31323334
+#define D 0x41424344
+
+#define W 0xc1c2c3c4
+#define X 0xd1d2d3d4
+#define Y 0xe1e2e3e4
+#define Z 0xf1f2f3f4
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v8hi.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v8hi.c
new file mode 100644
index 00000000000..ce442c5d995
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v8hi.c
@@ -0,0 +1,23 @@
+typedef unsigned short V __attribute__((vector_size(16)));
+typedef V VI;
+
+#define A1 0x1112
+#define B1 0x2122
+#define C1 0x3132
+#define D1 0x4142
+#define E1 0x5152
+#define F1 0x6162
+#define G1 0x7172
+#define H1 0x8182
+
+#define A2 0x9192
+#define B2 0xa1a2
+#define C2 0xb1b2
+#define D2 0xc1c2
+#define E2 0xd1d2
+#define F2 0xe1e2
+#define G2 0xf1f2
+#define H2 0x0102
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v8qi.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v8qi.c
new file mode 100644
index 00000000000..349ec6db699
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v8qi.c
@@ -0,0 +1,23 @@
+typedef unsigned char V __attribute__((vector_size(8)));
+typedef V VI;
+
+#define A1 0x11
+#define B1 0x12
+#define C1 0x13
+#define D1 0x14
+#define E1 0x15
+#define F1 0x16
+#define G1 0x17
+#define H1 0x18
+
+#define A2 0xf1
+#define B2 0xf2
+#define C2 0xf3
+#define D2 0xf4
+#define E2 0xf5
+#define F2 0xf6
+#define G2 0xf7
+#define H2 0xf8
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v8si.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v8si.c
new file mode 100644
index 00000000000..5b0a2c33e2c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v8si.c
@@ -0,0 +1,30 @@
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(32)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(32)));
+typedef V VI;
+#else
+# define UNSUPPORTED
+#endif
+
+#define A1 0x11121314
+#define B1 0x21222324
+#define C1 0x31323334
+#define D1 0x41424344
+#define E1 0x51525354
+#define F1 0x61626364
+#define G1 0x71727374
+#define H1 0x81828384
+
+#define A2 0x91929394
+#define B2 0xa1a2a3a4
+#define C2 0xb1b2b3b4
+#define D2 0xc1c2c3c4
+#define E2 0xd1d2d3d4
+#define F2 0xe1e2e3e4
+#define G2 0xf1f2f3f4
+#define H2 0x01020304
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/builtin-complex-err-1.c b/gcc/testsuite/gcc.dg/builtin-complex-err-1.c
index b9dab838786..3ef50da9278 100644
--- a/gcc/testsuite/gcc.dg/builtin-complex-err-1.c
+++ b/gcc/testsuite/gcc.dg/builtin-complex-err-1.c
@@ -19,8 +19,8 @@ _Complex float fc3 = __builtin_complex (1.0f, 1.0); /* { dg-error "different typ
void
f (void)
{
- __builtin_complex (0.0); /* { dg-error "expected" } */
- __builtin_complex (0.0, 0.0, 0.0); /* { dg-error "expected" } */
+ __builtin_complex (0.0); /* { dg-error "wrong number of arguments" } */
+ __builtin_complex (0.0, 0.0, 0.0); /* { dg-error "wrong number of arguments" } */
}
-void (*p) (void) = __builtin_complex; /* { dg-error "expected" } */
+void (*p) (void) = __builtin_complex; /* { dg-error "cannot take address" } */
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-12.c b/gcc/testsuite/gcc.dg/builtin-object-size-12.c
new file mode 100644
index 00000000000..b21eb0071b3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-12.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+struct S {
+ int len;
+ char s[0];
+};
+int main()
+{
+ char buf[sizeof (struct S) + 32];
+ if (__builtin_object_size (((struct S *)&buf[0])->s, 1) != 32)
+ abort ();
+ if (__builtin_object_size (((struct S *)&buf[1])->s, 1) != 31)
+ abort ();
+ if (__builtin_object_size (((struct S *)&buf[64])->s, 0) != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/builtins-47.c b/gcc/testsuite/gcc.dg/builtins-47.c
index b25ee1b9958..9513483cf30 100644
--- a/gcc/testsuite/gcc.dg/builtins-47.c
+++ b/gcc/testsuite/gcc.dg/builtins-47.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-ffast-math -fdump-tree-gimple" } */
+/* { dg-options "-O -ffast-math -fdump-tree-gimple" } */
extern double sqrt (double);
extern double pow (double, double);
diff --git a/gcc/testsuite/gcc.dg/builtins-67.c b/gcc/testsuite/gcc.dg/builtins-67.c
index 5c61391cc92..22267bd31b9 100644
--- a/gcc/testsuite/gcc.dg/builtins-67.c
+++ b/gcc/testsuite/gcc.dg/builtins-67.c
@@ -58,14 +58,14 @@ long long llceilf (float a) { return (long long) ceilf (a); }
long long llceill (long double a) { return (long long) ceill (a); }
#endif
-int iround (double a) { return (int) round (a); }
#ifdef HAVE_C99_RUNTIME
+int iround (double a) { return (int) round (a); }
int iroundf (float a) { return (int) roundf (a); }
int iroundl (long double a) { return (int) roundl (a); }
#endif
-int irint (double a) { return (int) rint (a); }
#ifdef HAVE_C99_RUNTIME
+int irint (double a) { return (int) rint (a); }
int irintf (float a) { return (int) rintf (a); }
int irintl (long double a) { return (int) rintl (a); }
#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c
new file mode 100644
index 00000000000..d975c8cee97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c
@@ -0,0 +1,21 @@
+/*
+ { dg-options "-ftrack-macro-expansion=1" }
+ { dg-do compile }
+*/
+
+#define OPERATE(OPRD1, OPRT, OPRD2) \
+do \
+{ \
+ OPRD1 OPRT OPRD2; /* { dg-message "expansion" }*/ \
+} while (0)
+
+#define SHIFTL(A,B) \
+ OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */
+
+void
+foo ()
+{
+ SHIFTL (0.1,0.2); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "invalid operands" "" { target *-*-* } 13 } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c
new file mode 100644
index 00000000000..684af4c7507
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c
@@ -0,0 +1,21 @@
+/*
+ { dg-options "-ftrack-macro-expansion=1" }
+ { dg-do compile }
+*/
+
+#define OPERATE(OPRD1, OPRT, OPRD2) \
+ OPRD1 OPRT OPRD2; /* { dg-message "expansion" } */
+
+#define SHIFTL(A,B) \
+ OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */
+
+#define MULT(A) \
+ SHIFTL (A,1) /* { dg-message "expanded|expansion" } */
+
+void
+foo ()
+{
+ MULT (1.0); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "invalid operands to binary <<" "" { target *-*-* } { 10 } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c
new file mode 100644
index 00000000000..119053ef9fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c
@@ -0,0 +1,14 @@
+/*
+ { dg-options "-fshow-column -ftrack-macro-expansion=1" }
+ { dg-do compile }
+ */
+
+#define SQUARE(A) A * A /* { dg-message "expansion" } */
+
+void
+foo()
+{
+ SQUARE (1 << 0.1); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "16:invalid operands to binary <<" "" {target *-*-* } { 11 } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c
new file mode 100644
index 00000000000..1f9fe6ad26c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c
@@ -0,0 +1,14 @@
+/*
+ { dg-options "-fshow-column -ftrack-macro-expansion=2" }
+ { dg-do compile }
+ */
+
+#define SQUARE(A) A * A /* { dg-message "expansion" } */
+
+void
+foo()
+{
+ SQUARE (1 << 0.1); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "13:invalid operands to binary <<" "" { target *-*-* } { 11 } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c
new file mode 100644
index 00000000000..3a2f9da1fce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c
@@ -0,0 +1,32 @@
+/*
+ { dg-options "-Wuninitialized" }
+ { dg-do compile }
+*/
+
+void f (unsigned);
+
+#define CODE_WITH_WARNING \
+ int a; \
+ f (a)
+
+#pragma GCC diagnostic ignored "-Wuninitialized"
+
+void
+g (void)
+{
+ CODE_WITH_WARNING;
+}
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic error "-Wuninitialized"
+
+void
+h (void)
+{
+ CODE_WITH_WARNING; /* { dg-error "uninitialized" } */
+}
+
+/*
+ { dg-message "some warnings being treated as errors" "" {target *-*-*} 0 }
+*/
diff --git a/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c
new file mode 100644
index 00000000000..7ab95b0c63b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c
@@ -0,0 +1,34 @@
+/*
+ { dg-options "-Wuninitialized -ftrack-macro-expansion=2" }
+ { dg-do compile }
+*/
+
+void f (unsigned);
+
+#define CODE_WITH_WARNING \
+ int a; /* { dg-message "expansion|declared here" } */ \
+ f (a) /* { dg-message "expansion" } */
+
+#pragma GCC diagnostic ignored "-Wuninitialized"
+
+void
+g (void)
+{
+ CODE_WITH_WARNING;
+}
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic error "-Wuninitialized"
+
+void
+h (void)
+{
+ CODE_WITH_WARNING; /* { dg-message "expanded" } */
+}
+
+/*
+ { dg-message "some warnings being treated as errors" "" {target *-*-*} 0 }
+*/
+
+/* { dg-error "uninitialized" "" { target *-*-* } { 10 } } */
diff --git a/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c b/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c
new file mode 100644
index 00000000000..82a4ea24617
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c
@@ -0,0 +1,164 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_longlong } */
+/* { dg-options "-std=gnu99" } */
+/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+
+
+/* Test basic functionality of the intrinsics. The operations should
+ not be optimized away if no one checks the return values. */
+
+/* Based on ia64-sync-[12].c, but 1) long on ARM is 32 bit so use long long
+ (an explicit 64bit type maybe a better bet) and 2) Use values that cross
+ the 32bit boundary and cause carries since the actual maths are done as
+ pairs of 32 bit instructions. */
+
+/* Note: This file is #included by some of the ARM tests. */
+
+__extension__ typedef __SIZE_TYPE__ size_t;
+
+extern void abort (void);
+extern void *memcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+/* Temporary space where the work actually gets done. */
+static long long AL[24];
+/* Values copied into AL before we start. */
+static long long init_di[24] = { 0x100000002ll, 0x200000003ll, 0, 1,
+
+ 0x100000002ll, 0x100000002ll,
+ 0x100000002ll, 0x100000002ll,
+
+ 0, 0x1000e0de0000ll,
+ 42 , 0xc001c0de0000ll,
+
+ -1ll, 0, 0xff00ff0000ll, -1ll,
+
+ 0, 0x1000e0de0000ll,
+ 42 , 0xc001c0de0000ll,
+
+ -1ll, 0, 0xff00ff0000ll, -1ll};
+/* This is what should be in AL at the end. */
+static long long test_di[24] = { 0x1234567890ll, 0x1234567890ll, 1, 0,
+
+ 0x100000002ll, 0x100000002ll,
+ 0x100000002ll, 0x100000002ll,
+
+ 1, 0xc001c0de0000ll,
+ 20, 0x1000e0de0000ll,
+
+ 0x300000007ll , 0x500000009ll,
+ 0xf100ff0001ll, ~0xa00000007ll,
+
+ 1, 0xc001c0de0000ll,
+ 20, 0x1000e0de0000ll,
+
+ 0x300000007ll , 0x500000009ll,
+ 0xf100ff0001ll, ~0xa00000007ll };
+
+/* First check they work in terms of what they do to memory. */
+static void
+do_noret_di (void)
+{
+ __sync_val_compare_and_swap (AL+0, 0x100000002ll, 0x1234567890ll);
+ __sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll);
+ __sync_lock_test_and_set (AL+2, 1);
+ __sync_lock_release (AL+3);
+
+ /* The following tests should not change the value since the
+ original does NOT match. */
+ __sync_val_compare_and_swap (AL+4, 0x000000002ll, 0x1234567890ll);
+ __sync_val_compare_and_swap (AL+5, 0x100000000ll, 0x1234567890ll);
+ __sync_bool_compare_and_swap (AL+6, 0x000000002ll, 0x1234567890ll);
+ __sync_bool_compare_and_swap (AL+7, 0x100000000ll, 0x1234567890ll);
+
+ __sync_fetch_and_add (AL+8, 1);
+ __sync_fetch_and_add (AL+9, 0xb000e0000000ll); /* + to both halves & carry. */
+ __sync_fetch_and_sub (AL+10, 22);
+ __sync_fetch_and_sub (AL+11, 0xb000e0000000ll);
+
+ __sync_fetch_and_and (AL+12, 0x300000007ll);
+ __sync_fetch_and_or (AL+13, 0x500000009ll);
+ __sync_fetch_and_xor (AL+14, 0xe00000001ll);
+ __sync_fetch_and_nand (AL+15, 0xa00000007ll);
+
+ /* These should be the same as the fetch_and_* cases except for
+ return value. */
+ __sync_add_and_fetch (AL+16, 1);
+ /* add to both halves & carry. */
+ __sync_add_and_fetch (AL+17, 0xb000e0000000ll);
+ __sync_sub_and_fetch (AL+18, 22);
+ __sync_sub_and_fetch (AL+19, 0xb000e0000000ll);
+
+ __sync_and_and_fetch (AL+20, 0x300000007ll);
+ __sync_or_and_fetch (AL+21, 0x500000009ll);
+ __sync_xor_and_fetch (AL+22, 0xe00000001ll);
+ __sync_nand_and_fetch (AL+23, 0xa00000007ll);
+}
+
+/* Now check return values. */
+static void
+do_ret_di (void)
+{
+ if (__sync_val_compare_and_swap (AL+0, 0x100000002ll, 0x1234567890ll) !=
+ 0x100000002ll) abort ();
+ if (__sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll) !=
+ 1) abort ();
+ if (__sync_lock_test_and_set (AL+2, 1) != 0) abort ();
+ __sync_lock_release (AL+3); /* no return value, but keep to match results. */
+
+ /* The following tests should not change the value since the
+ original does NOT match. */
+ if (__sync_val_compare_and_swap (AL+4, 0x000000002ll, 0x1234567890ll) !=
+ 0x100000002ll) abort ();
+ if (__sync_val_compare_and_swap (AL+5, 0x100000000ll, 0x1234567890ll) !=
+ 0x100000002ll) abort ();
+ if (__sync_bool_compare_and_swap (AL+6, 0x000000002ll, 0x1234567890ll) !=
+ 0) abort ();
+ if (__sync_bool_compare_and_swap (AL+7, 0x100000000ll, 0x1234567890ll) !=
+ 0) abort ();
+
+ if (__sync_fetch_and_add (AL+8, 1) != 0) abort ();
+ if (__sync_fetch_and_add (AL+9, 0xb000e0000000ll) != 0x1000e0de0000ll) abort ();
+ if (__sync_fetch_and_sub (AL+10, 22) != 42) abort ();
+ if (__sync_fetch_and_sub (AL+11, 0xb000e0000000ll) != 0xc001c0de0000ll)
+ abort ();
+
+ if (__sync_fetch_and_and (AL+12, 0x300000007ll) != -1ll) abort ();
+ if (__sync_fetch_and_or (AL+13, 0x500000009ll) != 0) abort ();
+ if (__sync_fetch_and_xor (AL+14, 0xe00000001ll) != 0xff00ff0000ll) abort ();
+ if (__sync_fetch_and_nand (AL+15, 0xa00000007ll) != -1ll) abort ();
+
+ /* These should be the same as the fetch_and_* cases except for
+ return value. */
+ if (__sync_add_and_fetch (AL+16, 1) != 1) abort ();
+ if (__sync_add_and_fetch (AL+17, 0xb000e0000000ll) != 0xc001c0de0000ll)
+ abort ();
+ if (__sync_sub_and_fetch (AL+18, 22) != 20) abort ();
+ if (__sync_sub_and_fetch (AL+19, 0xb000e0000000ll) != 0x1000e0de0000ll)
+ abort ();
+
+ if (__sync_and_and_fetch (AL+20, 0x300000007ll) != 0x300000007ll) abort ();
+ if (__sync_or_and_fetch (AL+21, 0x500000009ll) != 0x500000009ll) abort ();
+ if (__sync_xor_and_fetch (AL+22, 0xe00000001ll) != 0xf100ff0001ll) abort ();
+ if (__sync_nand_and_fetch (AL+23, 0xa00000007ll) != ~0xa00000007ll) abort ();
+}
+
+int main ()
+{
+ memcpy (AL, init_di, sizeof (init_di));
+
+ do_noret_di ();
+
+ if (memcmp (AL, test_di, sizeof (test_di)))
+ abort ();
+
+ memcpy (AL, init_di, sizeof (init_di));
+
+ do_ret_di ();
+
+ if (memcmp (AL, test_di, sizeof (test_di)))
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/di-sync-multithread.c b/gcc/testsuite/gcc.dg/di-sync-multithread.c
new file mode 100644
index 00000000000..c99878ea129
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/di-sync-multithread.c
@@ -0,0 +1,205 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_longlong } */
+/* { dg-require-effective-target pthread_h } */
+/* { dg-require-effective-target pthread } */
+/* { dg-options "-pthread -std=gnu99" } */
+
+/* test of long long atomic ops performed in parallel in 3 pthreads
+ david.gilbert@linaro.org */
+
+#include <pthread.h>
+#include <unistd.h>
+
+/*#define DEBUGIT 1 */
+
+#ifdef DEBUGIT
+#include <stdio.h>
+
+#define DOABORT(x,...) {\
+ fprintf (stderr, x, __VA_ARGS__); fflush (stderr); abort ();\
+ }
+
+#else
+
+#define DOABORT(x,...) abort ();
+
+#endif
+
+/* Passed to each thread to describe which bits it is going to work on. */
+struct threadwork {
+ unsigned long long count; /* incremented each time the worker loops. */
+ unsigned int thread; /* ID */
+ unsigned int addlsb; /* 8 bit */
+ unsigned int logic1lsb; /* 5 bit */
+ unsigned int logic2lsb; /* 8 bit */
+};
+
+/* The shared word where all the atomic work is done. */
+static volatile long long workspace;
+
+/* A shared word to tell the workers to quit when non-0. */
+static long long doquit;
+
+extern void abort (void);
+
+/* Note this test doesn't test the return values much. */
+void*
+worker (void* data)
+{
+ struct threadwork *tw = (struct threadwork*)data;
+ long long add1bit = 1ll << tw->addlsb;
+ long long logic1bit = 1ll << tw->logic1lsb;
+ long long logic2bit = 1ll << tw->logic2lsb;
+
+ /* Clear the bits we use. */
+ __sync_and_and_fetch (&workspace, ~(0xffll * add1bit));
+ __sync_fetch_and_and (&workspace, ~(0x1fll * logic1bit));
+ __sync_fetch_and_and (&workspace, ~(0xffll * logic2bit));
+
+ do
+ {
+ long long tmp1, tmp2, tmp3;
+ /* OK, lets try and do some stuff to the workspace - by the end
+ of the main loop our area should be the same as it is now - i.e. 0. */
+
+ /* Push the arithmetic section upto 128 - one of the threads will
+ case this to carry accross the 32bit boundary. */
+ for (tmp2 = 0; tmp2 < 64; tmp2++)
+ {
+ /* Add 2 using the two different adds. */
+ tmp1 = __sync_add_and_fetch (&workspace, add1bit);
+ tmp3 = __sync_fetch_and_add (&workspace, add1bit);
+
+ /* The value should be the intermediate add value in both cases. */
+ if ((tmp1 & (add1bit * 0xff)) != (tmp3 & (add1bit * 0xff)))
+ DOABORT ("Mismatch of add intermediates on thread %d "
+ "workspace=0x%llx tmp1=0x%llx "
+ "tmp2=0x%llx tmp3=0x%llx\n",
+ tw->thread, workspace, tmp1, tmp2, tmp3);
+ }
+
+ /* Set the logic bits. */
+ tmp2=__sync_or_and_fetch (&workspace,
+ 0x1fll * logic1bit | 0xffll * logic2bit);
+
+ /* Check the logic bits are set and the arithmetic value is correct. */
+ if ((tmp2 & (0x1fll * logic1bit | 0xffll * logic2bit
+ | 0xffll * add1bit))
+ != (0x1fll * logic1bit | 0xffll * logic2bit | 0x80ll * add1bit))
+ DOABORT ("Midloop check failed on thread %d "
+ "workspace=0x%llx tmp2=0x%llx "
+ "masktmp2=0x%llx expected=0x%llx\n",
+ tw->thread, workspace, tmp2,
+ tmp2 & (0x1fll * logic1bit | 0xffll * logic2bit |
+ 0xffll * add1bit),
+ (0x1fll * logic1bit | 0xffll * logic2bit | 0x80ll * add1bit));
+
+ /* Pull the arithmetic set back down to 0 - again this should cause a
+ carry across the 32bit boundary in one thread. */
+
+ for (tmp2 = 0; tmp2 < 64; tmp2++)
+ {
+ /* Subtract 2 using the two different subs. */
+ tmp1=__sync_sub_and_fetch (&workspace, add1bit);
+ tmp3=__sync_fetch_and_sub (&workspace, add1bit);
+
+ /* The value should be the intermediate sub value in both cases. */
+ if ((tmp1 & (add1bit * 0xff)) != (tmp3 & (add1bit * 0xff)))
+ DOABORT ("Mismatch of sub intermediates on thread %d "
+ "workspace=0x%llx tmp1=0x%llx "
+ "tmp2=0x%llx tmp3=0x%llx\n",
+ tw->thread, workspace, tmp1, tmp2, tmp3);
+ }
+
+
+ /* Clear the logic bits. */
+ __sync_fetch_and_xor (&workspace, 0x1fll * logic1bit);
+ tmp3=__sync_and_and_fetch (&workspace, ~(0xffll * logic2bit));
+
+ /* The logic bits and the arithmetic bits should be zero again. */
+ if (tmp3 & (0x1fll * logic1bit | 0xffll * logic2bit | 0xffll * add1bit))
+ DOABORT ("End of worker loop; bits none 0 on thread %d "
+ "workspace=0x%llx tmp3=0x%llx "
+ "mask=0x%llx maskedtmp3=0x%llx\n",
+ tw->thread, workspace, tmp3, (0x1fll * logic1bit |
+ 0xffll * logic2bit | 0xffll * add1bit),
+ tmp3 & (0x1fll * logic1bit | 0xffll * logic2bit | 0xffll * add1bit));
+
+ __sync_add_and_fetch (&tw->count, 1);
+ }
+ while (!__sync_bool_compare_and_swap (&doquit, 1, 1));
+
+ pthread_exit (0);
+}
+
+int
+main ()
+{
+ /* We have 3 threads doing three sets of operations, an 8 bit
+ arithmetic field, a 5 bit logic field and an 8 bit logic
+ field (just to pack them all in).
+
+ 6 5 4 4 3 2 1
+ 3 6 8 0 2 4 6 8 0
+ |...,...|...,...|...,...|...,...|...,...|...,...|...,...|...,...
+ - T0 -- T1 -- T2 --T2 -- T0 -*- T2-- T1-- T1 -***- T0-
+ logic2 logic2 arith log2 arith log1 log1 arith log1
+
+ */
+ unsigned int t;
+ long long tmp;
+ int err;
+
+ struct threadwork tw[3]={
+ { 0ll, 0, 27, 0, 56 },
+ { 0ll, 1, 8,16, 48 },
+ { 0ll, 2, 40,21, 35 }
+ };
+
+ pthread_t threads[3];
+
+ __sync_lock_release (&doquit);
+
+ /* Get the work space into a known value - All 1's. */
+ __sync_lock_release (&workspace); /* Now all 0. */
+ tmp = __sync_val_compare_and_swap (&workspace, 0, -1ll);
+ if (tmp!=0)
+ DOABORT ("Initial __sync_val_compare_and_swap wasn't 0 workspace=0x%llx "
+ "tmp=0x%llx\n", workspace,tmp);
+
+ for (t = 0; t < 3; t++)
+ {
+ err=pthread_create (&threads[t], NULL , worker, &tw[t]);
+ if (err) DOABORT ("pthread_create failed on thread %d with error %d\n",
+ t, err);
+ };
+
+ sleep (5);
+
+ /* Stop please. */
+ __sync_lock_test_and_set (&doquit, 1ll);
+
+ for (t = 0; t < 3; t++)
+ {
+ err=pthread_join (threads[t], NULL);
+ if (err)
+ DOABORT ("pthread_join failed on thread %d with error %d\n", t, err);
+ };
+
+ __sync_synchronize ();
+
+ /* OK, so all the workers have finished -
+ the workers should have zero'd their workspace, the unused areas
+ should still be 1. */
+ if (!__sync_bool_compare_and_swap (&workspace, 0x040000e0ll, 0))
+ DOABORT ("End of run workspace mismatch, got %llx\n", workspace);
+
+ /* All the workers should have done some work. */
+ for (t = 0; t < 3; t++)
+ {
+ if (tw[t].count == 0) DOABORT ("Worker %d gave 0 count\n", t);
+ };
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/graphite/id-pr46845.c b/gcc/testsuite/gcc.dg/graphite/id-pr46845.c
index f4da78eda35..45807217b79 100644
--- a/gcc/testsuite/gcc.dg/graphite/id-pr46845.c
+++ b/gcc/testsuite/gcc.dg/graphite/id-pr46845.c
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -ffast-math -fgraphite-identity -w -Wno-psabi" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ffast-math -fgraphite-identity -w -Wno-psabi" { target { i?86-*-* x86_64-*-* powerpc*-*-* } } } */
typedef float V2SF __attribute__ ((vector_size (128)));
diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-14.c b/gcc/testsuite/gcc.dg/graphite/interchange-14.c
index cf620338381..b0d93a18c66 100644
--- a/gcc/testsuite/gcc.dg/graphite/interchange-14.c
+++ b/gcc/testsuite/gcc.dg/graphite/interchange-14.c
@@ -55,5 +55,5 @@ main (void)
}
/* PRE destroys the perfect nest and we can't cope with that yet. */
-/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-15.c b/gcc/testsuite/gcc.dg/graphite/interchange-15.c
index ee7aed6bca7..d154b743f89 100644
--- a/gcc/testsuite/gcc.dg/graphite/interchange-15.c
+++ b/gcc/testsuite/gcc.dg/graphite/interchange-15.c
@@ -49,6 +49,6 @@ main (void)
}
/* PRE destroys the perfect nest and we can't cope with that yet. */
-/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c b/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c
index 11f8b2ae1cf..f446dbe622f 100644
--- a/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c
+++ b/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c
@@ -59,6 +59,6 @@ main (void)
}
/* PRE destroys the perfect nest and we can't cope with that yet. */
-/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/inline-5.c b/gcc/testsuite/gcc.dg/ipa/inline-5.c
index 121f7815bcd..8da31ef369b 100644
--- a/gcc/testsuite/gcc.dg/ipa/inline-5.c
+++ b/gcc/testsuite/gcc.dg/ipa/inline-5.c
@@ -33,3 +33,4 @@ accessreference (struct a *a)
/* { dg-final { scan-ipa-dump-times "Will be eliminated" 4 "inline" } } */
/* { dg-final { scan-ipa-dump-times "50. will be eliminated" 1 "inline" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */
diff --git a/gcc/testsuite/gcc.dg/lto/20081222_1.c b/gcc/testsuite/gcc.dg/lto/20081222_1.c
index e8f9254421b..755eb9918e9 100644
--- a/gcc/testsuite/gcc.dg/lto/20081222_1.c
+++ b/gcc/testsuite/gcc.dg/lto/20081222_1.c
@@ -1,8 +1,12 @@
#include "20081222_0.h"
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
/* Actually, call "x" "INT_X", and make it hidden. */
extern __typeof (x) x
- __asm__ ("INT_x")
+ __asm__ (ASMNAME ("INT_x"))
__attribute__ ((__visibility__ ("hidden")));
int x ()
@@ -12,5 +16,5 @@ int x ()
/* Make an externally-visible symbol "X" that's an alias for INT_x. */
extern __typeof (x) EXT_x
- __asm__ ("x")
+ __asm__ (ASMNAME ("x"))
__attribute__ ((__alias__ ("INT_x")));
diff --git a/gcc/testsuite/gcc.dg/memcpy-4.c b/gcc/testsuite/gcc.dg/memcpy-4.c
new file mode 100644
index 00000000000..4fe72ec5b89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memcpy-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-expand" } */
+
+void
+f1 (char *p)
+{
+ __builtin_memcpy (p, "123", 3);
+}
+
+/* { dg-final { scan-rtl-dump-times "mem/s/u" 3 "expand" { target mips*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "expand" } } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir1.c b/gcc/testsuite/gcc.dg/plugin/plugindir1.c
index a973ec0c54c..72821ac9852 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir1.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir1.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-options "-c -fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir2.c b/gcc/testsuite/gcc.dg/plugin/plugindir2.c
index 58c1505501a..063b9d9e594 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir2.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir2.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-options "-save-temps -c -fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir3.c b/gcc/testsuite/gcc.dg/plugin/plugindir3.c
index 41037534a26..9b1c004cfd1 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir3.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir3.c
@@ -1,4 +1,4 @@
/* { dg-do preprocess } */
/* { dg-options "-fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir4.c b/gcc/testsuite/gcc.dg/plugin/plugindir4.c
index 27b2f24aaf9..8f1cb801621 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir4.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir4.c
@@ -1,4 +1,4 @@
/* { dg-do preprocess } */
/* { dg-options "-iplugindir=my-plugindir -fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*my-plugindir/foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*my-plugindir/foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/pr47276.c b/gcc/testsuite/gcc.dg/pr47276.c
index 3fa1a0e49a8..9276b1a6854 100644
--- a/gcc/testsuite/gcc.dg/pr47276.c
+++ b/gcc/testsuite/gcc.dg/pr47276.c
@@ -1,6 +1,11 @@
/* { dg-do compile } */
/* { dg-require-alias "" } */
/* { dg-require-visibility "" } */
+
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
extern void syslog (int __pri, __const char *__fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
extern void vsyslog (int __pri, __const char *__fmt, int __ap)
@@ -17,15 +22,15 @@ void
__vsyslog_chk(int pri, int flag, const char *fmt, int ap)
{
}
-extern __typeof (__vsyslog_chk) __EI___vsyslog_chk __asm__("" "__vsyslog_chk"); extern __typeof (__vsyslog_chk) __EI___vsyslog_chk __attribute__((alias ("" "__GI___vsyslog_chk")));
+extern __typeof (__vsyslog_chk) __EI___vsyslog_chk __asm__("" ASMNAME ("__vsyslog_chk")); extern __typeof (__vsyslog_chk) __EI___vsyslog_chk __attribute__((alias ("" "__GI___vsyslog_chk")));
void
__syslog(int pri, const char *fmt, ...)
{
}
extern __typeof (__syslog) syslog __attribute__ ((alias ("__syslog")));
-extern __typeof (syslog) __EI_syslog __asm__("" "syslog"); extern __typeof (syslog) __EI_syslog __attribute__((alias ("" "__GI_syslog")));
+extern __typeof (syslog) __EI_syslog __asm__("" ASMNAME ("syslog")); extern __typeof (syslog) __EI_syslog __attribute__((alias ("" "__GI_syslog")));
extern __typeof (__vsyslog) vsyslog __attribute__ ((alias ("__vsyslog")));
-extern __typeof (vsyslog) __EI_vsyslog __asm__("" "vsyslog"); extern __typeof (vsyslog) __EI_vsyslog __attribute__((alias ("" "__GI_vsyslog")));
-extern __typeof (syslog) syslog __asm__ ("" "__GI_syslog") __attribute__ ((visibility ("hidden")));
-extern __typeof (vsyslog) vsyslog __asm__ ("" "__GI_vsyslog") __attribute__ ((visibility ("hidden")));
-extern __typeof (__vsyslog_chk) __vsyslog_chk __asm__ ("" "__GI___vsyslog_chk") __attribute__ ((visibility ("hidden")));
+extern __typeof (vsyslog) __EI_vsyslog __asm__("" ASMNAME ("vsyslog")); extern __typeof (vsyslog) __EI_vsyslog __attribute__((alias ("" "__GI_vsyslog")));
+extern __typeof (syslog) syslog __asm__ ("" ASMNAME ("__GI_syslog")) __attribute__ ((visibility ("hidden")));
+extern __typeof (vsyslog) vsyslog __asm__ ("" ASMNAME ("__GI_vsyslog")) __attribute__ ((visibility ("hidden")));
+extern __typeof (__vsyslog_chk) __vsyslog_chk __asm__ ("" ASMNAME ("__GI___vsyslog_chk")) __attribute__ ((visibility ("hidden")));
diff --git a/gcc/testsuite/gcc.dg/pr49696.c b/gcc/testsuite/gcc.dg/pr49696.c
new file mode 100644
index 00000000000..8e5a018fc02
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr49696.c
@@ -0,0 +1,29 @@
+/* { dg-require-effective-target sync_char_short } */
+
+/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+
+void
+foo (short *x)
+{
+ __sync_val_compare_and_swap (x, 1, 0);
+ __sync_bool_compare_and_swap (x, 1, 0);
+ __sync_lock_test_and_set (x, 0);
+
+ __sync_fetch_and_add (x, 0);
+ __sync_fetch_and_add (x, 0);
+ __sync_fetch_and_add (x, 0);
+ __sync_fetch_and_sub (x, 0);
+ __sync_fetch_and_and (x, 0);
+ __sync_fetch_and_or (x, 0);
+ __sync_fetch_and_xor (x, 0);
+ __sync_fetch_and_nand (x, 0);
+
+ __sync_add_and_fetch (x, 0);
+ __sync_add_and_fetch (x, 0);
+ __sync_add_and_fetch (x, 0);
+ __sync_sub_and_fetch (x, 0);
+ __sync_and_and_fetch (x, 0);
+ __sync_or_and_fetch (x, 0);
+ __sync_xor_and_fetch (x, 0);
+ __sync_nand_and_fetch (x, 0);
+}
diff --git a/gcc/testsuite/gcc.dg/pr49994-3.c b/gcc/testsuite/gcc.dg/pr49994-3.c
index 538779675f4..c24aa8ffbdc 100644
--- a/gcc/testsuite/gcc.dg/pr49994-3.c
+++ b/gcc/testsuite/gcc.dg/pr49994-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fsched2-use-superblocks -g" } */
+/* { dg-options "-O2 -fsched2-use-superblocks -g -mbackchain" { target s390*-*-* } } */
/* { dg-require-effective-target scheduling } */
void *
diff --git a/gcc/testsuite/gcc.dg/pr50193-1.c b/gcc/testsuite/gcc.dg/pr50193-1.c
new file mode 100644
index 00000000000..6abc9c40570
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50193-1.c
@@ -0,0 +1,10 @@
+/* PR 50193: ARM: ICE on a | (b << negative-constant) */
+/* Ensure that the compiler doesn't ICE. */
+
+/* { dg-options "-O2" } */
+
+int
+foo(int a, int b)
+{
+ return a | (b << -3); /* { dg-warning "left shift count is negative" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr50205.c b/gcc/testsuite/gcc.dg/pr50205.c
new file mode 100644
index 00000000000..ff523d07f37
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50205.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target powerpc*-*-* ia64-*-* i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -fno-cprop-registers -fno-dce -fno-forward-propagate -fselective-scheduling2 -funroll-loops -fno-web" } */
+extern int a[];
+
+void foo (void)
+{
+ int i;
+ for (i = 0; i < 199; i++)
+ {
+ if (a[i] != i)
+ __builtin_abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr50340.c b/gcc/testsuite/gcc.dg/pr50340.c
new file mode 100644
index 00000000000..18430366fe1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50340.c
@@ -0,0 +1,46 @@
+/* { dg-do compile { target powerpc*-*-* ia64-*-* i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O3 -fselective-scheduling2 -funroll-loops" } */
+extern int mode_size[];
+typedef unsigned HARD_REG_SET[ ((64 + 32 - 1) / 32) ];
+enum reload_type {
+ RELOAD_FOR_INPUT,
+ RELOAD_FOR_OUTPUT,
+ RELOAD_FOR_INSN,
+ RELOAD_FOR_INPUT_ADDRESS,
+ RELOAD_FOR_OUTPUT_ADDRESS,
+ RELOAD_FOR_OPERAND_ADDRESS,
+ RELOAD_FOR_OPADDR_ADDR,
+ RELOAD_OTHER,
+ RELOAD_FOR_OTHER_ADDRESS
+};
+static HARD_REG_SET reload_reg_used;
+static HARD_REG_SET reload_reg_used_in_input_addr[10];
+static HARD_REG_SET reload_reg_used_in_output_addr[10];
+static HARD_REG_SET reload_reg_used_in_input[10];
+static HARD_REG_SET reload_reg_used_in_output[10];
+static HARD_REG_SET reload_reg_used_in_op_addr;
+static HARD_REG_SET reload_reg_used_in_op_addr_reload;
+static HARD_REG_SET reload_reg_used_in_insn;
+static HARD_REG_SET reload_reg_used_in_other_addr;
+static HARD_REG_SET reload_reg_used_at_all;
+void __attribute__((cold)) mark_reload_reg_in_use (regno, opnum, type, mode)
+{
+ int nregs = regno ? 1 : mode_size[mode];
+ int i;
+ for (i = regno; i < nregs + regno; i++)
+ {
+ switch (type)
+ {
+ case RELOAD_OTHER: reload_reg_used[i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_INPUT_ADDRESS: reload_reg_used_in_input_addr[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OUTPUT_ADDRESS: reload_reg_used_in_output_addr[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OPERAND_ADDRESS: reload_reg_used_in_op_addr[i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OPADDR_ADDR: reload_reg_used_in_op_addr_reload[i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OTHER_ADDRESS: reload_reg_used_in_other_addr[i / 32u] |= 1; break;
+ case RELOAD_FOR_INPUT: reload_reg_used_in_input[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OUTPUT: reload_reg_used_in_output[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_INSN: reload_reg_used_in_insn[i / 32u] |= 1 << i % 32u;
+ }
+ reload_reg_used_at_all[i / 32u] |= 1 << i;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr50527.c b/gcc/testsuite/gcc.dg/pr50527.c
new file mode 100644
index 00000000000..87fae9659d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50527.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-Os --param large-stack-frame=30" } */
+
+extern void abort (void);
+
+void __attribute__((noinline))
+bar (char *a)
+{
+}
+
+void __attribute__((noinline))
+foo (char *a, int b)
+{
+}
+
+void __attribute__((noinline))
+test_align (char *p, int aligned, unsigned int mask)
+{
+ int p_aligned = ((unsigned long int)p & mask) == 0;
+ if (aligned != p_aligned)
+ abort ();
+}
+
+int
+main ()
+{
+ const int kIterations = 4;
+ char results[kIterations];
+ int i;
+ unsigned int mask;
+
+ mask = 0xf;
+ test_align (results, ((unsigned long int)results & mask) == 0, mask);
+ mask = 0x7;
+ test_align (results, ((unsigned long int)results & mask) == 0, mask);
+ mask = 0x3;
+ test_align (results, ((unsigned long int)results & mask) == 0, mask);
+ mask = 0x1;
+ test_align (results, ((unsigned long int)results & mask) == 0, mask);
+
+ bar (results);
+ for (i = 0; i < kIterations; i++)
+ foo ("%d ", results[i]);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr50604.c b/gcc/testsuite/gcc.dg/pr50604.c
new file mode 100644
index 00000000000..1ab465a1095
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50604.c
@@ -0,0 +1,19 @@
+/* PR tree-optimization/50604 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include "strlenopt.h"
+
+typedef char T;
+extern const T s[];
+
+void
+foo (T *x)
+{
+ char *r = malloc (strlen (x));
+ strcpy (r, s);
+ strcat (r, x);
+ strcat (r, "/");
+}
+
+const T s[] = "abcdefghijklmnopq";
diff --git a/gcc/testsuite/gcc.dg/pr50613.c b/gcc/testsuite/gcc.dg/pr50613.c
new file mode 100644
index 00000000000..27c6fba3636
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50613.c
@@ -0,0 +1,20 @@
+/* PR tree-optimization/50613 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-ccp" } */
+
+#include "strlenopt.h"
+
+char buf[26];
+
+static inline void
+bar (char *__restrict dest, const char *__restrict src)
+{
+ strcpy (dest, src);
+}
+
+void
+foo (char *p)
+{
+ if (strlen (p) < 50)
+ bar (buf, p);
+}
diff --git a/gcc/testsuite/gcc.dg/pr50717-1.c b/gcc/testsuite/gcc.dg/pr50717-1.c
new file mode 100644
index 00000000000..afbe542a2be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50717-1.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/50717 */
+/* Ensure that widening multiply-and-accumulate is not used where integer
+ type promotion or users' casts should prevent it. */
+
+/* { dg-options "-O2 -fdump-tree-widening_mul" } */
+
+long long
+f (unsigned int a, char b, long long c)
+{
+ return (a * b) + c;
+}
+
+int
+g (short a, short b, int c)
+{
+ return (short)(a * b) + c;
+}
+
+int
+h (char a, char b, int c)
+{
+ return (char)(a * b) + c;
+}
+
+/* { dg-final { scan-tree-dump-times "WIDEN_MULT_PLUS_EXPR" 0 "widening_mul" } } */
+/* { dg-final { cleanup-tree-dump "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/README b/gcc/testsuite/gcc.dg/simulate-thread/README
new file mode 100644
index 00000000000..5588e04d6db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/simulate-thread/README
@@ -0,0 +1,118 @@
+OVERVIEW
+--------
+
+This is a harness to test the atomicity of certain operations, and to
+make sure the compiler does not introduce data races in a
+multi-threaded environment.
+
+The basic premise is that we set up testcases such that the thing we
+want test, say an atomic instruction which stores a double word is in
+a function of its own. We then run this testcase within GDB,
+controlled by a gdb script (simulate-thread.gdb). The gdb script will
+break on the function to be tested, and then single step through every
+machine instruction in the function. We set this up so GDB can make a
+couple of inferior function calls before and after each of these
+single step instructions for a couple of purposes:
+
+ 1. One of the calls simulates another thread running in the
+ process which changes or access memory.
+
+ 2. The other calls are used to verify that we always get the
+ expected behavior.
+
+For example, in the case of an atomic store, anyone looking at the
+memory associated with an atomic variable should never see any in
+between states. If you have an atomic long long int, and it starts
+with the value 0, and you write the value MAX_LONG_LONG, any other
+thread looking at that variable should never see anything other than 0
+or MAX_LONG_LONG. If you implement the atomic write as a sequence of
+2 stores, it is possible for another thread to read the location after
+the first store, but before the second one is complete. That thread
+would then see an in-between state (one word would still be 0).
+
+We simulate this in the testcase by having GDB step through the
+program, instruction by instruction, and after each step, making an
+inferior function call which looks at the value of the atomic variable
+and verifies that it sees either 0 or MAX_LONG_LONG. If it sees any
+other value, it fails the testcase.
+
+This way, we are *sure* there is no in between state because we
+effectively acted like an OS and switched to another thread after
+every single instruction of the routine is executed and looked at the
+results each time.
+
+We use the same idea to test for data races to see if an illegal load
+has been hoisted, or that two parallel bitfield writes don't overlap
+in a data race.
+
+Below is a skeleton of how a test should look like. For more details,
+look at the tests themselves.
+
+ANATOMY OF A TEST
+-----------------
+
+/* { dg-do link } */
+/* { dg-options "-some-flags" } */
+/* { dg-final { simulate-thread } } */
+
+/* NOTE: Any failure must be indicated by displaying "FAIL:". */
+
+#include "simulate-thread.h"
+
+/* Called before each instruction, simulating another thread executing. */
+void simulate_thread_other_threads()
+{
+}
+
+/* Called after each instruction. Returns 1 if any inconsistency is
+ found, 0 otherwise. */
+int simulate_thread_step_verify()
+{
+ if (some_problem)
+ {
+ printf("FAIL: reason\n");
+ return 1;
+ }
+ return 0;
+}
+
+/* Called at the end of the program (simulate_thread_fini == 1). Verifies
+ the state of the program and returns 1 if any inconsistency is
+ found, 0 otherwise. */
+int simulate_thread_final_verify()
+{
+ if (some_problem)
+ {
+ printf("FAIL: reason\n");
+ return 1;
+ }
+ return 0;
+}
+
+/* The gdb script will break on simulate_thread_main(), so make sure
+ GCC does not inline it, thus making the break point fail. */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+ /* Do stuff. */
+}
+
+int main()
+{
+
+ /* Perform any setup code that will run outside of the testing
+ harness. Put code here that you do NOT want to be interrupted on
+ an instruction basis. E.g., setup code, and system library
+ calls. */
+
+ /* Do un-instrumented stuff. */
+ /* ... */
+
+ /* Start the instrumented show. */
+ simulate_thread_main();
+
+ /* Must be called at the end of the test. */
+ simulate_thread_done();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.exp b/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.exp
new file mode 100644
index 00000000000..6d47388cadf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.exp
@@ -0,0 +1,38 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Your run of the mill dg test, but verify that we have a working GDB first.
+
+load_lib gcc-dg.exp
+load_lib gcc-simulate-thread.exp
+load_lib torture-options.exp
+
+dg-init
+torture-init
+set-torture-options [list \
+ { -O0 -g } \
+ { -O1 -g } \
+ { -O2 -g } \
+ { -O3 -g } \
+ { -Os -g } ]
+
+if [gdb-exists] {
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] ""
+ gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/simulate-thread/*.c]] ""
+}
+
+torture-finish
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.gdb b/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.gdb
new file mode 100644
index 00000000000..c7bac73f4f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.gdb
@@ -0,0 +1,17 @@
+set height 0
+break simulate_thread_main
+disp/i $pc
+run
+
+set $ret = 0
+while (simulate_thread_fini != 1) && (! $ret)
+ call simulate_thread_wrapper_other_threads()
+ stepi
+ set $ret |= simulate_thread_step_verify()
+end
+
+if (! $ret)
+ set $ret |= simulate_thread_wrapper_final_verify()
+end
+continue
+quit $ret
diff --git a/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.h b/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.h
new file mode 100644
index 00000000000..9e2361faa06
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/simulate-thread/simulate-thread.h
@@ -0,0 +1,111 @@
+int simulate_thread_fini = 0;
+
+void __attribute__((noinline))
+simulate_thread_done ()
+{
+ simulate_thread_fini = 1;
+}
+
+/* A hostile thread is one which changes a memory location so quickly
+ that another thread may never see the same value again. This is
+ simulated when simulate_thread_other_thread() is defined to modify
+ a memory location every cycle.
+
+ A process implementing a dependency on this value can run into
+ difficulties with such a hostile thread. For instance,
+ implementing an add with a compare_and_swap loop goes something
+ like:
+
+ expected = *mem;
+ loop:
+ new = expected += value;
+ if (!succeed (expected = compare_and_swap (mem, expected, new)))
+ goto loop;
+
+ If the content of 'mem' are changed every cycle by
+ simulate_thread_other_thread () this will become an infinite loop
+ since the value *mem will never be 'expected' by the time the
+ compare_and_swap is executed.
+
+ HOSTILE_THREAD_THRESHOLD defines the number of intructions which a
+ program will execute before triggering the hostile thread
+ pause. The pause will last for HOSTILE_THREAD_PAUSE instructions,
+ and then the counter will reset and begin again. During the pause
+ period, simulate_thread_other_thread will not be called.
+
+ This provides a chance for forward progress to be made and the
+ infinite loop to be avoided.
+
+ If the testcase defines HOSTILE_PAUSE_ERROR, then it will be
+ considered an RUNTIME FAILURE if the hostile pause is triggered.
+ This will allow to test for guaranteed forward progress routines.
+
+ If the default values for HOSTILE_THREAD_THRESHOLD or
+ HOSTILE_THREAD_PAUSE are insufficient, then the testcase may
+ override these by defining the values before including this file.
+
+ Most testcase are intended to run for very short periods of time,
+ so these defaults are considered to be high enough to not trigger
+ on a typical case, but not drag the test time out too much if a
+ hostile condition is interferring. */
+
+
+/* Define the threshold to start pausing the hostile thread. */
+#if !defined (HOSTILE_THREAD_THRESHOLD)
+#define HOSTILE_THREAD_THRESHOLD 500
+#endif
+
+/* Define the length of pause in cycles for the hostile thread to pause to
+ allow forward progress to be made. */
+#if !defined (HOSTILE_THREAD_PAUSE)
+#define HOSTILE_THREAD_PAUSE 20
+#endif
+
+void simulate_thread_other_threads (void);
+int simulate_thread_final_verify (void);
+
+static int simulate_thread_hostile_pause = 0;
+
+/* This function wraps simulate_thread_other_threads an monitors for
+ an infinite loop. If the threshold value HOSTILE_THREAD_THRESHOLD
+ is reached, the other_thread process is paused for
+ HOSTILE_THREAD_PAUSE cycles before resuming, and the counters start
+ again. */
+void
+simulate_thread_wrapper_other_threads()
+{
+ static int count = 0;
+ static int pause = 0;
+
+ if (++count >= HOSTILE_THREAD_THRESHOLD)
+ {
+ if (!simulate_thread_hostile_pause)
+ simulate_thread_hostile_pause = 1;
+
+ /* Count cycles before calling the hostile thread again. */
+ if (pause++ < HOSTILE_THREAD_PAUSE)
+ return;
+
+ /* Reset the pause counter, as well as the thread counter. */
+ pause = 0;
+ count = 0;
+ }
+ simulate_thread_other_threads ();
+}
+
+
+/* If the test case defines HOSTILE_PAUSE_ERROR, then the test case
+ will fail execution if it had a hostile pause. */
+int
+simulate_thread_wrapper_final_verify ()
+{
+ int ret = simulate_thread_final_verify ();
+#if defined (HOSTILE_PAUSE_ERROR)
+ if (simulate_thread_hostile_pause)
+ {
+ printf ("FAIL: Forward progress made only by pausing hostile thread\n");
+ ret = ret | 1; /* 0 indicates proper comnpletion. */
+ }
+#endif
+ return ret;
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt-21.c b/gcc/testsuite/gcc.dg/strlenopt-21.c
index cd5fc5d928f..1f27c33400d 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-21.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-21.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O2 -fdump-tree-strlen -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
#include "strlenopt.h"
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c b/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c
index 63df2d26305..0c2f98b832a 100644
--- a/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c
+++ b/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c
@@ -1,6 +1,7 @@
/* Test __builtin_complex semantics. */
/* { dg-do run } */
/* { dg-options "-std=c1x -pedantic-errors" } */
+/* { dg-add-options ieee } */
extern void exit (int);
extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/torture/pr48044.c b/gcc/testsuite/gcc.dg/torture/pr48044.c
index fe3b73402cc..d20a634a119 100644
--- a/gcc/testsuite/gcc.dg/torture/pr48044.c
+++ b/gcc/testsuite/gcc.dg/torture/pr48044.c
@@ -2,6 +2,10 @@
/* { dg-do compile } */
/* { dg-require-alias "" } */
-int a __asm__ ("b") = 0;
-extern int c __asm__ ("a") __attribute__ ((alias ("b")));
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
+int a __asm__ (ASMNAME ("b")) = 0;
+extern int c __asm__ (ASMNAME ("a")) __attribute__ ((alias ("b")));
extern int d __attribute__ ((weak, alias ("a")));
diff --git a/gcc/testsuite/gcc.dg/torture/pr50389.c b/gcc/testsuite/gcc.dg/torture/pr50389.c
new file mode 100644
index 00000000000..6d8b095b8ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50389.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-freorder-blocks -ftracer" } */
+
+extern int data[];
+extern int i;
+
+void
+foo (void)
+{
+ char buf[8];
+ __builtin___memcpy_chk (buf, data, i ? 8 : 4,
+ __builtin_object_size (buf, 0));
+ __builtin___memcpy_chk (buf, data, i ? 8 : 4,
+ __builtin_object_size (buf, 0));
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50723.c b/gcc/testsuite/gcc.dg/torture/pr50723.c
new file mode 100644
index 00000000000..24e490fc618
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50723.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+typedef short unsigned int wchar_t;
+typedef unsigned int size_t;
+int* _errno(void);
+int WideCharToMultiByte (wchar_t *);
+int __attribute__ ((__nonnull__ (1)))
+__wcrtomb_cp (char *dst, wchar_t wc, const unsigned int cp,
+ const unsigned int mb_max)
+{
+ if (cp == 0) {
+ if (wc > 255)
+ (*_errno()) = 42;
+ return 1;
+ }
+ else
+ return WideCharToMultiByte (&wc);
+}
+void wcsrtombs (char *dst, const wchar_t *pwc, unsigned int cp,
+ unsigned int mb_max)
+{
+ if ((__wcrtomb_cp (dst, *pwc, cp, mb_max)) <= 0)
+ return;
+ if ((__wcrtomb_cp (dst, *pwc, cp, mb_max)) <= 0)
+ return;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50729.c b/gcc/testsuite/gcc.dg/torture/pr50729.c
new file mode 100644
index 00000000000..a1daa7b851f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50729.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+extern void abort (void);
+unsigned short __attribute__((noinline))
+foo (int i)
+{
+ if (i >= 0
+ && i <= 0x400000)
+ return (unsigned short)(signed char)i;
+ return i;
+}
+int main()
+{
+ int i;
+ for (i = 0; i < 0xffff; ++i)
+ if (foo(i) != (unsigned short)(signed char) i)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50767.c b/gcc/testsuite/gcc.dg/torture/pr50767.c
new file mode 100644
index 00000000000..96ab72ebd7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50767.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-tree-copy-prop -fno-tree-dominator-opts" } */
+
+struct S
+{
+ struct S *s;
+};
+
+static struct S *ss;
+struct S *s;
+
+void bar(void);
+
+void foo(void)
+{
+ for (;;)
+ {
+ s->s = ss;
+ bar ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50768.c b/gcc/testsuite/gcc.dg/torture/pr50768.c
new file mode 100644
index 00000000000..351b2f96618
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50768.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-ftracer" } */
+
+char data[8];
+int l1;
+
+void
+test1 (void)
+{
+ char buf[8];
+ __builtin___mempcpy_chk (buf, data, l1 ? sizeof (buf) : 4,
+ __builtin_object_size (buf, 0));
+ if (__builtin___memmove_chk
+ (buf, data, l1 ? sizeof (buf) : 4,
+ __builtin_object_size (buf, 0)) != buf)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/restrict-1.c b/gcc/testsuite/gcc.dg/torture/restrict-1.c
new file mode 100644
index 00000000000..e7af4f538ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/restrict-1.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+extern void abort (void);
+void __attribute__((noinline,noclone))
+foo (int ** __restrict__ p, int ** __restrict__ q)
+{
+ **p = **q;
+}
+int main()
+{
+ int x = 0, y = 1, *i = &x, *j = &y;
+ foo (&i, &j);
+ if (x != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-16.inc b/gcc/testsuite/gcc.dg/torture/vshuf-16.inc
new file mode 100644
index 00000000000..1464774c62f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-16.inc
@@ -0,0 +1,133 @@
+#define N 16
+#define TESTS \
+T (0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) \
+T (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+T (2, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7) \
+T (3, 0, 18, 7, 16, 23, 5, 4, 22, 1, 6, 21, 20, 19, 3, 17, 2) \
+T (4, 0, 1, 2, 3, 4, 5, 6, 7, 7, 1, 2, 0, 4, 5, 6, 3) \
+T (5, 0, 19, 16, 3, 2, 17, 18, 1, 24, 8, 11, 10, 27, 26, 25, 9) \
+T (6, 4, 23, 20, 7, 6, 21, 22, 5, 28, 12, 15, 14, 31, 30, 29, 13) \
+T (7, 7, 1, 2, 0, 4, 5, 6, 3, 7, 1, 2, 0, 4, 5, 6, 3) \
+T (8, 7, 3, 0, 5, 4, 1, 6, 2, 31, 27, 24, 29, 28, 25, 30, 26) \
+T (9, 7, 1, 2, 0, 4, 5, 6, 3, 15, 9, 14, 10, 8, 12, 13, 11) \
+T (10, 15, 0, 3, 12, 14, 2, 1, 13, 4, 11, 9, 6, 5, 10, 7, 8) \
+T (11, 15, 9, 14, 10, 8, 12, 13, 11, 7, 1, 2, 0, 4, 5, 6, 3) \
+T (12, 2, 5, 24, 23, 17, 22, 20, 21, 12, 14, 13, 8, 6, 20, 10, 18) \
+T (13, 23, 11, 15, 9, 0, 14, 8, 12, 10, 13, 19, 11, 2, 26, 24, 30) \
+T (14, 25, 5, 17, 1, 9, 15, 21, 7, 28, 2, 18, 13, 30, 14, 10, 4) \
+T (15, 1, 30, 27, 31, 9, 18, 25, 12, 7, 4, 2, 16, 25, 20, 10, 3) \
+T (16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30) \
+T (17, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31)
+#define EXPTESTS \
+T (116, 28, 13, 27, 11, 21, 1, 5, 22, 29, 14, 15, 6, 3, 10, 16, 30) \
+T (117, 22, 26, 1, 13, 29, 3, 18, 18, 11, 21, 12, 28, 19, 5, 7, 4) \
+T (118, 1, 28, 26, 11, 4, 27, 30, 12, 10, 19, 6, 7, 13, 31, 0, 24) \
+T (119, 7, 30, 17, 27, 0, 10, 13, 21, 3, 29, 24, 21, 12, 6, 15, 18) \
+T (120, 28, 13, 26, 24, 21, 16, 29, 9, 10, 2, 27, 19, 20, 17, 18, 14) \
+T (121, 22, 21, 1, 8, 14, 15, 0, 28, 25, 30, 10, 17, 19, 27, 26, 13) \
+T (122, 28, 13, 27, 2, 21, 29, 22, 4, 8, 0, 18, 1, 31, 7, 19, 14) \
+T (123, 15, 0, 9, 2, 31, 3, 17, 24, 1, 8, 26, 20, 30, 11, 22, 5) \
+T (124, 28, 14, 5, 7, 9, 10, 21, 31, 2, 11, 22, 27, 7, 27, 30, 2) \
+T (125, 17, 13, 1, 7, 20, 22, 8, 15, 4, 25, 10, 28, 23, 24, 9, 21) \
+T (126, 17, 5, 3, 4, 0, 7, 19, 13, 29, 25, 26, 1, 15, 8, 2, 7) \
+T (127, 16, 6, 3, 22, 31, 15, 13, 21, 14, 20, 29, 17, 18, 2, 23, 25) \
+T (128, 18, 22, 21, 28, 10, 13, 6, 17, 29, 20, 7, 16, 2, 9, 1, 11) \
+T (129, 30, 11, 11, 22, 21, 10, 3, 18, 15, 26, 20, 16, 17, 13, 29, 7) \
+T (130, 5, 9, 21, 16, 29, 11, 4, 2, 17, 28, 3, 19, 9, 10, 13, 20) \
+T (131, 13, 3, 19, 25, 1, 28, 31, 30, 10, 12, 21, 26, 27, 14, 5, 17) \
+T (132, 8, 28, 26, 31, 5, 14, 4, 13, 6, 15, 3, 17, 6, 20, 27, 29) \
+T (133, 7, 26, 8, 17, 31, 11, 25, 16, 19, 4, 0, 27, 7, 20, 19, 13) \
+T (134, 14, 23, 19, 4, 9, 11, 16, 6, 7, 3, 27, 20, 24, 18, 26, 31) \
+T (135, 7, 25, 14, 2, 16, 5, 29, 3, 4, 24, 21, 9, 20, 19, 27, 1) \
+T (136, 5, 14, 29, 12, 3, 3, 1, 4, 8, 7, 9, 13, 10, 4, 12, 23) \
+T (137, 2, 6, 21, 28, 5, 23, 16, 24, 22, 18, 30, 12, 31, 16, 4, 1) \
+T (138, 4, 31, 11, 26, 16, 23, 5, 12, 15, 14, 19, 3, 18, 21, 27, 6) \
+T (139, 29, 14, 19, 18, 23, 27, 16, 7, 8, 26, 0, 12, 15, 17, 9, 1) \
+T (140, 18, 27, 20, 31, 8, 10, 9, 17, 13, 19, 12, 15, 28, 3, 25, 5) \
+T (141, 28, 13, 23, 20, 10, 5, 22, 17, 27, 0, 21, 27, 11, 25, 24, 30) \
+T (142, 24, 17, 31, 22, 9, 15, 28, 6, 12, 23, 30, 1, 21, 5, 27, 29) \
+T (143, 12, 19, 16, 0, 8, 15, 13, 22, 17, 4, 31, 20, 2, 9, 21, 30) \
+T (144, 5, 13, 26, 12, 27, 0, 17, 1, 25, 8, 10, 25, 18, 11, 29, 4) \
+T (145, 6, 18, 13, 29, 14, 31, 16, 10, 2, 12, 20, 25, 23, 28, 24, 10) \
+T (146, 17, 0, 21, 0, 12, 13, 16, 5, 19, 29, 30, 27, 4, 9, 1, 20) \
+T (147, 14, 26, 28, 17, 31, 10, 6, 3, 29, 22, 18, 1, 6, 5, 30, 8) \
+T (148, 10, 17, 12, 18, 26, 16, 5, 24, 2, 7, 20, 15, 30, 2, 29, 25) \
+T (149, 30, 27, 15, 23, 8, 12, 29, 2, 4, 9, 25, 13, 21, 7, 16, 20) \
+T (150, 7, 13, 4, 22, 24, 0, 31, 28, 18, 5, 2, 16, 17, 1, 1, 6) \
+T (151, 24, 27, 17, 25, 27, 6, 14, 30, 21, 19, 23, 29, 12, 19, 15, 9) \
+T (152, 1, 16, 24, 19, 29, 27, 17, 9, 8, 23, 22, 12, 11, 2, 26, 25) \
+T (153, 2, 25, 22, 8, 11, 16, 20, 26, 29, 15, 6, 15, 30, 10, 21, 24) \
+T (154, 19, 20, 23, 11, 20, 1, 18, 29, 21, 24, 6, 8, 19, 2, 4, 9) \
+T (155, 30, 12, 29, 21, 7, 8, 31, 15, 3, 1, 10, 4, 2, 9, 19, 2) \
+T (156, 14, 27, 5, 23, 15, 22, 4, 26, 30, 19, 29, 18, 16, 24, 21, 7) \
+T (157, 14, 15, 26, 17, 30, 16, 6, 0, 10, 8, 2, 23, 20, 13, 3, 27) \
+T (158, 2, 14, 13, 22, 24, 26, 17, 16, 4, 27, 7, 31, 9, 1, 28, 3) \
+T (159, 13, 15, 19, 12, 31, 23, 16, 8, 0, 2, 17, 27, 30, 14, 18, 1) \
+T (160, 3, 9, 30, 28, 31, 24, 5, 1, 23, 0, 13, 24, 20, 18, 3, 26) \
+T (161, 6, 10, 28, 8, 15, 14, 17, 26, 9, 0, 11, 2, 16, 2, 27, 24) \
+T (162, 20, 29, 7, 11, 5, 21, 0, 8, 12, 28, 13, 4, 26, 10, 28, 23) \
+T (163, 31, 25, 24, 10, 18, 3, 5, 12, 18, 2, 17, 22, 30, 16, 8, 6) \
+T (164, 0, 5, 22, 3, 21, 28, 31, 20, 12, 14, 18, 4, 13, 2, 0, 29) \
+T (165, 26, 18, 25, 20, 2, 0, 10, 30, 27, 11, 9, 3, 31, 4, 29, 21) \
+T (166, 15, 21, 3, 9, 22, 6, 29, 13, 24, 30, 31, 5, 26, 17, 0, 12) \
+T (167, 3, 28, 19, 27, 26, 14, 5, 10, 16, 24, 12, 30, 23, 13, 18, 26) \
+T (168, 0, 13, 10, 16, 23, 17, 8, 24, 20, 25, 21, 3, 12, 22, 6, 1) \
+T (169, 11, 18, 7, 26, 23, 6, 24, 21, 29, 18, 7, 19, 12, 31, 15, 28) \
+T (170, 14, 5, 21, 6, 9, 11, 12, 4, 0, 8, 30, 10, 24, 19, 18, 3) \
+T (171, 6, 3, 5, 13, 10, 2, 24, 31, 23, 2, 29, 4, 22, 7, 19, 20) \
+T (172, 12, 26, 13, 18, 19, 9, 1, 27, 14, 7, 20, 31, 11, 8, 30, 4) \
+T (173, 1, 23, 10, 31, 12, 26, 6, 13, 7, 30, 18, 4, 0, 27, 21, 19) \
+T (174, 20, 15, 13, 22, 10, 14, 5, 3, 31, 8, 0, 11, 4, 9, 1, 0) \
+T (175, 12, 29, 23, 28, 8, 20, 19, 7, 20, 24, 6, 26, 11, 17, 2, 5) \
+T (176, 19, 0, 31, 26, 30, 16, 17, 14, 5, 7, 3, 27, 1, 22, 29, 9) \
+T (177, 17, 15, 4, 1, 7, 13, 23, 28, 2, 8, 26, 12, 21, 24, 3, 19) \
+T (178, 17, 23, 21, 2, 12, 27, 8, 15, 6, 25, 7, 28, 4, 26, 1, 23) \
+T (179, 17, 25, 19, 4, 7, 20, 13, 30, 18, 3, 25, 21, 24, 26, 16, 31) \
+T (180, 7, 20, 18, 9, 3, 16, 12, 22, 0, 30, 10, 25, 17, 29, 19, 5) \
+T (181, 4, 17, 23, 1, 16, 22, 12, 31, 25, 9, 8, 21, 26, 15, 29, 29) \
+T (182, 31, 25, 14, 17, 8, 24, 4, 29, 27, 0, 20, 5, 13, 12, 5, 30) \
+T (183, 29, 26, 3, 22, 24, 30, 0, 15, 19, 7, 18, 6, 25, 14, 3, 3) \
+T (184, 23, 22, 7, 18, 10, 30, 29, 6, 16, 13, 11, 28, 5, 26, 4, 24) \
+T (185, 27, 15, 8, 29, 21, 23, 12, 11, 26, 22, 21, 6, 10, 23, 20, 27) \
+T (186, 19, 23, 20, 7, 8, 14, 6, 17, 20, 1, 5, 12, 25, 18, 10, 29) \
+T (187, 12, 14, 2, 5, 31, 21, 30, 18, 2, 6, 17, 22, 22, 28, 0, 18) \
+T (188, 10, 8, 13, 29, 20, 18, 8, 5, 4, 3, 26, 19, 24, 29, 6, 30) \
+T (189, 23, 19, 8, 2, 21, 18, 26, 1, 27, 12, 10, 4, 3, 20, 10, 17) \
+T (190, 31, 30, 21, 8, 15, 9, 3, 22, 7, 17, 25, 5, 13, 6, 1, 11) \
+T (191, 0, 5, 26, 6, 18, 1, 9, 31, 11, 3, 10, 23, 30, 27, 17, 14) \
+T (192, 19, 7, 29, 27, 8, 17, 22, 20, 10, 22, 2, 11, 9, 14, 31, 23) \
+T (193, 3, 23, 10, 18, 14, 9, 4, 24, 8, 30, 9, 13, 16, 17, 4, 22) \
+T (194, 13, 22, 8, 3, 9, 24, 9, 7, 15, 17, 26, 19, 11, 5, 18, 24) \
+T (195, 1, 18, 17, 13, 14, 0, 6, 15, 31, 22, 9, 2, 23, 19, 20, 3) \
+T (196, 9, 8, 17, 4, 28, 20, 6, 1, 11, 12, 23, 0, 15, 27, 31, 18) \
+T (197, 11, 2, 16, 1, 29, 21, 14, 9, 23, 30, 22, 8, 27, 9, 18, 10) \
+T (198, 10, 6, 26, 22, 13, 28, 18, 31, 4, 17, 27, 5, 7, 25, 20, 21) \
+T (199, 9, 8, 0, 0, 10, 7, 4, 24, 16, 3, 20, 1, 31, 11, 17, 26) \
+T (200, 19, 24, 31, 25, 7, 4, 14, 4, 9, 21, 29, 30, 10, 16, 6, 13) \
+T (201, 27, 4, 25, 12, 11, 3, 29, 1, 16, 6, 12, 5, 26, 25, 10, 15) \
+T (202, 11, 28, 9, 3, 20, 30, 18, 6, 13, 12, 25, 24, 5, 26, 0, 31) \
+T (203, 7, 23, 14, 16, 1, 31, 3, 0, 18, 6, 4, 10, 11, 15, 13, 29) \
+T (204, 28, 15, 6, 4, 21, 18, 22, 29, 13, 3, 18, 27, 21, 7, 31, 26) \
+T (205, 2, 13, 7, 22, 21, 9, 24, 15, 6, 20, 14, 29, 16, 27, 31, 0) \
+T (206, 23, 3, 13, 0, 18, 19, 10, 29, 16, 22, 21, 30, 17, 5, 6, 31) \
+T (207, 0, 3, 6, 29, 7, 10, 20, 17, 5, 8, 27, 18, 12, 4, 30, 28) \
+T (208, 5, 31, 20, 6, 14, 11, 28, 19, 7, 25, 27, 26, 10, 8, 22, 4) \
+T (209, 26, 22, 12, 9, 25, 0, 21, 14, 4, 7, 17, 30, 29, 24, 13, 31) \
+T (210, 15, 1, 6, 10, 26, 12, 8, 25, 3, 31, 23, 5, 30, 2, 0, 27) \
+T (211, 2, 11, 1, 27, 4, 17, 28, 22, 5, 28, 16, 20, 6, 3, 0, 15) \
+T (212, 25, 2, 6, 18, 16, 12, 4, 27, 1, 29, 7, 3, 21, 20, 17, 19) \
+T (213, 16, 0, 19, 21, 29, 23, 18, 31, 24, 12, 4, 20, 2, 8, 27, 30) \
+T (214, 20, 28, 9, 28, 22, 13, 2, 0, 8, 26, 10, 23, 24, 12, 31, 11) \
+T (215, 27, 22, 12, 15, 10, 20, 4, 25, 29, 9, 17, 3, 28, 21, 31, 23) \
+T (216, 16, 29, 20, 19, 16, 6, 18, 28, 3, 15, 29, 30, 1, 22, 10, 0) \
+T (217, 24, 14, 27, 3, 16, 30, 6, 0, 13, 12, 19, 7, 11, 20, 5, 26) \
+T (218, 19, 30, 26, 17, 13, 5, 10, 15, 16, 28, 24, 20, 0, 25, 9, 14) \
+T (219, 11, 0, 29, 5, 16, 30, 22, 19, 25, 4, 17, 7, 18, 2, 14, 13) \
+T (220, 27, 9, 16, 10, 19, 23, 12, 21, 3, 30, 18, 4, 15, 6, 29, 13) \
+T (221, 26, 12, 25, 22, 11, 18, 1, 7, 0, 19, 29, 31, 8, 4, 9, 15) \
+T (222, 18, 23, 31, 7, 26, 5, 15, 11, 25, 4, 22, 21, 14, 10, 20, 8) \
+T (223, 2, 18, 4, 24, 6, 20, 9, 25, 16, 3, 5, 22, 10, 7, 23, 30) \
+T (224, 4, 13, 6, 8, 22, 2, 12, 24, 31, 29, 20, 23, 0, 10, 1, 3) \
+T (225, 26, 3, 30, 18, 4, 19, 22, 31, 28, 24, 15, 14, 1, 23, 27, 7) \
+T (226, 18, 6, 23, 16, 25, 26, 17, 5, 28, 10, 30, 24, 12, 14, 15, 20) \
+T (227, 5, 19, 23, 22, 1, 7, 26, 12, 30, 17, 0, 0, 10, 6, 18, 4)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-2.inc b/gcc/testsuite/gcc.dg/torture/vshuf-2.inc
new file mode 100644
index 00000000000..70b2e5c139a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-2.inc
@@ -0,0 +1,19 @@
+#define N 2
+#define TESTS \
+T (0, 0, 0) \
+T (1, 0, 1) \
+T (2, 0, 2) \
+T (3, 0, 3) \
+T (4, 1, 0) \
+T (5, 1, 1) \
+T (6, 1, 2) \
+T (7, 1, 3) \
+T (8, 2, 0) \
+T (9, 2, 1) \
+T (10, 2, 2) \
+T (11, 2, 3) \
+T (12, 3, 0) \
+T (13, 3, 1) \
+T (14, 3, 2) \
+T (15, 3, 3)
+#define EXPTESTS
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-32.inc b/gcc/testsuite/gcc.dg/torture/vshuf-32.inc
new file mode 100644
index 00000000000..8410e48310d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-32.inc
@@ -0,0 +1,133 @@
+#define N 32
+#define TESTS \
+T (0, 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) \
+T (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+T (2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) \
+T (3, 26, 60, 14, 40, 44, 51, 12, 45, 9, 37, 4, 47, 35, 63, 54, 30, 28, 10, 48, 32, 5, 59, 7, 52, 11, 6, 62, 49, 25, 25, 20, 55) \
+T (4, 32, 16, 54, 20, 62, 60, 56, 9, 38, 26, 42, 12, 17, 51, 4, 58, 59, 25, 50, 27, 41, 37, 8, 30, 18, 24, 40, 36, 25, 7, 37, 63) \
+T (5, 0, 4, 60, 9, 23, 19, 45, 6, 5, 12, 38, 60, 34, 36, 26, 11, 47, 52, 63, 39, 7, 56, 17, 54, 53, 39, 18, 2, 37, 55, 22, 21) \
+T (6, 2, 44, 46, 13, 40, 38, 52, 10, 50, 55, 11, 15, 9, 0, 12, 42, 45, 19, 11, 34, 26, 24, 62, 25, 5, 17, 1, 47, 21, 7, 60, 41) \
+T (7, 50, 13, 37, 62, 9, 49, 14, 53, 15, 42, 36, 1, 33, 27, 63, 41, 57, 12, 7, 2, 44, 48, 16, 39, 25, 31, 20, 10, 3, 60, 43, 21) \
+T (8, 1, 37, 22, 61, 5, 14, 46, 47, 6, 35, 10, 48, 30, 26, 33, 13, 18, 18, 11, 21, 44, 29, 60, 45, 19, 37, 7, 43, 36, 1, 28, 59) \
+T (9, 30, 44, 42, 51, 6, 7, 38, 13, 43, 31, 58, 0, 56, 17, 27, 32, 10, 53, 3, 29, 21, 12, 15, 50, 28, 24, 16, 61, 9, 34, 59, 19) \
+T (10, 20, 49, 50, 14, 54, 53, 33, 40, 46, 15, 0, 28, 25, 30, 10, 17, 51, 59, 26, 13, 45, 27, 2, 61, 4, 36, 8, 0, 18, 33, 22, 63) \
+T (11, 13, 40, 7, 33, 51, 21, 59, 46, 47, 32, 9, 34, 63, 35, 41, 17, 24, 1, 8, 26, 52, 62, 11, 22, 37, 28, 5, 39, 10, 53, 60, 2) \
+T (12, 39, 43, 54, 27, 53, 39, 27, 30, 2, 17, 13, 33, 7, 52, 40, 15, 36, 57, 10, 28, 22, 23, 25, 24, 41, 47, 8, 20, 5, 3, 4, 0) \
+T (13, 7, 51, 13, 61, 25, 4, 19, 58, 35, 33, 29, 15, 40, 2, 39, 16, 38, 3, 54, 63, 15, 6, 48, 21, 14, 52, 17, 50, 34, 55, 57, 50) \
+T (14, 22, 53, 28, 42, 45, 38, 49, 13, 54, 61, 21, 52, 7, 16, 34, 9, 1, 43, 62, 43, 35, 50, 47, 58, 20, 3, 30, 15, 37, 53, 43, 36) \
+T (15, 2, 43, 49, 34, 28, 35, 29, 36, 51, 9, 17, 48, 10, 37, 45, 21, 52, 19, 25, 33, 60, 31, 30, 42, 12, 26, 27, 46, 5, 40, 14, 36) \
+T (16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62) \
+T (17, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63)
+#define EXPTESTS \
+T (116, 13, 38, 47, 3, 17, 8, 38, 20, 59, 61, 39, 26, 7, 49, 63, 43, 57, 16, 40, 19, 4, 32, 27, 7, 52, 19, 46, 55, 36, 41, 48, 6) \
+T (117, 39, 35, 59, 20, 56, 18, 58, 63, 57, 14, 2, 16, 5, 61, 35, 4, 53, 9, 52, 51, 27, 33, 61, 12, 3, 35, 36, 40, 37, 7, 45, 42) \
+T (118, 4, 5, 8, 14, 35, 12, 55, 34, 6, 53, 60, 5, 48, 56, 22, 18, 62, 44, 38, 31, 28, 16, 33, 36, 43, 26, 16, 23, 37, 47, 51, 3) \
+T (119, 26, 50, 53, 27, 6, 29, 14, 19, 23, 48, 39, 8, 58, 0, 12, 15, 17, 41, 33, 18, 52, 31, 10, 9, 49, 13, 51, 45, 47, 60, 35, 57) \
+T (120, 37, 60, 13, 55, 52, 42, 5, 22, 17, 59, 0, 21, 59, 11, 25, 56, 62, 56, 31, 54, 9, 47, 28, 6, 44, 33, 61, 12, 19, 16, 8, 40) \
+T (121, 47, 45, 44, 40, 22, 17, 4, 31, 8, 52, 34, 32, 41, 21, 62, 37, 5, 13, 58, 27, 0, 17, 33, 57, 42, 57, 18, 43, 61, 36, 38, 14) \
+T (122, 31, 16, 42, 6, 34, 2, 12, 20, 57, 29, 23, 60, 24, 10, 17, 0, 21, 32, 45, 5, 19, 30, 59, 4, 9, 1, 46, 14, 26, 63, 3, 22) \
+T (123, 46, 61, 50, 1, 38, 37, 62, 40, 10, 49, 44, 26, 16, 24, 5, 2, 39, 20, 15, 30, 34, 29, 57, 27, 47, 55, 8, 44, 36, 4, 9, 25) \
+T (124, 45, 53, 7, 48, 23, 21, 20, 7, 13, 4, 22, 24, 39, 0, 63, 60, 18, 37, 34, 36, 54, 49, 1, 1, 38, 27, 17, 57, 27, 14, 59, 62) \
+T (125, 30, 57, 46, 21, 51, 23, 25, 62, 29, 12, 51, 15, 41, 33, 16, 56, 19, 61, 27, 49, 41, 40, 55, 54, 44, 43, 2, 26, 34, 22, 11, 20) \
+T (126, 26, 29, 15, 57, 6, 15, 30, 10, 53, 24, 19, 52, 23, 43, 20, 1, 18, 29, 56, 51, 38, 8, 51, 2, 4, 41, 62, 12, 7, 63, 3, 33) \
+T (127, 42, 10, 36, 2, 41, 34, 19, 2, 46, 27, 5, 55, 15, 22, 36, 26, 30, 58, 51, 61, 18, 48, 24, 21, 56, 7, 14, 47, 17, 6, 0, 8) \
+T (128, 34, 23, 16, 20, 15, 13, 3, 30, 59, 46, 54, 24, 26, 45, 17, 48, 4, 27, 7, 31, 2, 41, 1, 28, 51, 12, 63, 8, 32, 19, 18, 33) \
+T (129, 3, 41, 62, 28, 30, 63, 24, 5, 33, 60, 55, 32, 37, 45, 56, 52, 50, 35, 26, 38, 10, 40, 15, 14, 17, 58, 46, 41, 11, 34, 48, 2) \
+T (130, 59, 60, 24, 20, 61, 39, 43, 37, 53, 32, 8, 44, 28, 13, 36, 58, 0, 42, 60, 55, 31, 57, 56, 10, 18, 3, 5, 12, 18, 34, 49, 54) \
+T (131, 3, 62, 16, 40, 38, 32, 5, 54, 53, 28, 63, 20, 12, 14, 50, 4, 13, 34, 32, 29, 26, 18, 25, 52, 2, 42, 30, 59, 43, 41, 27, 10) \
+T (132, 35, 31, 57, 52, 4, 0, 61, 21, 15, 3, 9, 54, 38, 13, 24, 30, 37, 58, 41, 6, 49, 32, 12, 28, 19, 59, 14, 42, 16, 48, 56, 23) \
+T (133, 62, 12, 13, 50, 26, 32, 45, 10, 48, 55, 49, 8, 24, 42, 52, 57, 53, 3, 54, 38, 33, 43, 7, 26, 23, 6, 21, 61, 18, 7, 51, 44) \
+T (134, 31, 15, 38, 39, 60, 14, 5, 21, 53, 6, 9, 43, 12, 36, 32, 40, 30, 10, 56, 51, 50, 35, 38, 3, 37, 13, 2, 24, 63, 34, 55, 34) \
+T (135, 29, 36, 22, 7, 63, 23, 19, 20, 12, 58, 13, 50, 41, 1, 59, 33, 46, 39, 52, 11, 8, 51, 62, 42, 31, 10, 58, 38, 45, 4, 32, 53) \
+T (136, 19, 20, 47, 13, 22, 10, 14, 37, 35, 31, 8, 15, 32, 54, 43, 40, 4, 9, 1, 32, 12, 29, 23, 60, 52, 51, 39, 52, 56, 6, 26, 11) \
+T (137, 39, 11, 49, 34, 37, 51, 32, 63, 26, 62, 16, 49, 14, 5, 7, 3, 59, 33, 54, 58, 61, 9, 47, 36, 13, 23, 28, 2, 40, 4, 44, 1) \
+T (138, 53, 24, 33, 35, 19, 49, 55, 34, 44, 27, 40, 47, 38, 17, 25, 39, 60, 4, 26, 15, 7, 36, 55, 51, 39, 20, 45, 62, 57, 50, 57, 21) \
+T (139, 24, 58, 16, 63, 7, 20, 18, 9, 35, 48, 12, 54, 0, 62, 41, 42, 25, 50, 17, 61, 51, 37, 4, 55, 33, 22, 12, 40, 53, 26, 47, 29) \
+T (140, 55, 53, 40, 61, 63, 57, 46, 17, 8, 56, 4, 29, 27, 32, 24, 52, 5, 13, 12, 5, 44, 30, 26, 3, 22, 0, 47, 19, 39, 50, 38, 15) \
+T (141, 15, 46, 3, 18, 3, 55, 22, 39, 10, 62, 61, 38, 48, 16, 6, 45, 11, 60, 5, 26, 4, 50, 24, 59, 47, 8, 29, 53, 12, 21, 43, 58) \
+T (142, 22, 8, 21, 6, 55, 10, 55, 20, 59, 19, 55, 23, 52, 39, 46, 49, 20, 1, 40, 5, 12, 14, 57, 50, 29, 2, 37, 31, 62, 18, 34, 54) \
+T (143, 54, 28, 50, 0, 62, 18, 10, 8, 13, 29, 52, 8, 5, 36, 35, 4, 58, 19, 56, 29, 38, 30, 55, 51, 40, 34, 53, 26, 33, 59, 12, 27) \
+T (144, 42, 4, 35, 20, 52, 3, 10, 21, 17, 63, 62, 40, 15, 41, 54, 39, 8, 57, 5, 45, 37, 38, 1, 43, 32, 58, 6, 50, 33, 3, 55, 9) \
+T (145, 27, 62, 49, 14, 19, 39, 61, 40, 22, 20, 10, 22, 34, 43, 9, 46, 31, 42, 54, 23, 35, 50, 4, 3, 41, 24, 8, 30, 9, 45, 48, 17) \
+T (146, 4, 40, 22, 45, 8, 35, 9, 24, 9, 41, 7, 47, 49, 58, 51, 43, 54, 37, 18, 39, 56, 1, 46, 0, 33, 38, 15, 13, 17, 31, 54, 2) \
+T (147, 55, 19, 20, 3, 41, 8, 49, 36, 28, 38, 1, 11, 44, 55, 32, 15, 59, 0, 63, 50, 2, 16, 61, 21, 14, 23, 30, 22, 33, 46, 48, 62) \
+T (148, 30, 40, 59, 11, 9, 8, 50, 42, 10, 6, 58, 22, 45, 60, 63, 4, 49, 31, 5, 7, 25, 18, 52, 13, 53, 0, 0, 39, 24, 48, 3, 20) \
+T (149, 41, 1, 63, 11, 49, 24, 26, 51, 31, 57, 7, 36, 46, 4, 53, 19, 29, 21, 30, 14, 10, 48, 38, 13, 59, 25, 44, 43, 35, 61, 33, 16) \
+T (150, 38, 44, 5, 26, 25, 42, 16, 15, 43, 28, 41, 3, 52, 62, 50, 11, 6, 35, 13, 12, 57, 24, 32, 31, 39, 55, 46, 33, 0, 18, 4, 47) \
+T (151, 45, 29, 60, 15, 6, 36, 53, 18, 54, 47, 61, 13, 3, 50, 21, 27, 28, 21, 7, 63, 26, 34, 9, 24, 52, 46, 38, 56, 48, 59, 31, 2) \
+T (152, 32, 23, 3, 13, 35, 55, 18, 19, 42, 29, 48, 54, 53, 30, 17, 62, 37, 38, 31, 32, 6, 61, 7, 10, 52, 8, 27, 12, 59, 50, 36, 28) \
+T (153, 37, 63, 52, 6, 46, 43, 28, 51, 7, 25, 59, 26, 42, 40, 22, 5, 4, 58, 54, 44, 41, 32, 53, 14, 39, 17, 30, 61, 24, 45, 31, 47) \
+T (154, 33, 38, 42, 58, 12, 10, 8, 25, 3, 63, 55, 37, 31, 30, 2, 0, 59, 34, 43, 11, 36, 27, 49, 28, 22, 60, 48, 20, 1, 6, 35, 47) \
+T (155, 57, 2, 6, 50, 16, 12, 36, 59, 1, 61, 39, 35, 21, 20, 17, 51, 48, 32, 19, 53, 29, 23, 18, 31, 24, 4, 52, 8, 27, 62, 60, 9) \
+T (156, 60, 54, 13, 2, 32, 8, 58, 42, 23, 24, 12, 63, 43, 59, 22, 44, 15, 20, 4, 57, 61, 27, 47, 9, 49, 35, 28, 21, 48, 52, 19, 48) \
+T (157, 61, 38, 50, 28, 35, 15, 29, 51, 30, 20, 1, 54, 10, 0, 24, 46, 59, 3, 16, 32, 45, 12, 7, 11, 48, 37, 26, 19, 62, 49, 13, 5) \
+T (158, 10, 15, 16, 60, 24, 52, 19, 0, 25, 41, 46, 11, 29, 5, 62, 22, 43, 36, 17, 7, 18, 34, 49, 45, 59, 9, 42, 51, 55, 44, 21, 3) \
+T (159, 30, 18, 51, 36, 21, 15, 6, 61, 13, 58, 44, 25, 57, 22, 11, 54, 33, 39, 43, 0, 26, 19, 29, 63, 8, 4, 41, 23, 31, 58, 5, 47) \
+T (160, 43, 57, 36, 22, 21, 46, 53, 50, 63, 10, 20, 52, 8, 34, 18, 4, 56, 38, 41, 48, 35, 5, 39, 23, 54, 30, 4, 13, 40, 45, 2, 12) \
+T (161, 24, 31, 61, 52, 55, 36, 32, 10, 33, 3, 58, 35, 62, 50, 51, 54, 63, 30, 28, 4, 26, 47, 14, 56, 23, 59, 39, 38, 16, 25, 17, 37) \
+T (162, 60, 17, 42, 30, 56, 12, 14, 47, 6, 20, 5, 19, 55, 54, 33, 39, 58, 30, 22, 32, 0, 7, 18, 4, 63, 48, 36, 10, 3, 21, 28, 35) \
+T (163, 11, 12, 21, 42, 0, 50, 48, 35, 20, 48, 38, 46, 52, 36, 43, 31, 28, 52, 48, 27, 1, 13, 60, 58, 39, 16, 32, 37, 57, 53, 24, 41) \
+T (164, 10, 17, 45, 30, 36, 24, 55, 59, 5, 50, 15, 56, 13, 38, 25, 29, 53, 20, 6, 1, 26, 51, 36, 32, 23, 35, 62, 3, 34, 10, 12, 52) \
+T (165, 15, 0, 34, 40, 12, 13, 28, 39, 39, 20, 48, 14, 22, 27, 51, 34, 11, 18, 16, 38, 62, 58, 6, 41, 44, 42, 36, 7, 33, 37, 37, 5) \
+T (166, 35, 44, 35, 56, 39, 57, 11, 35, 1, 0, 61, 31, 52, 32, 33, 24, 37, 49, 18, 29, 24, 12, 5, 43, 55, 25, 60, 40, 4, 30, 38, 3) \
+T (167, 25, 2, 53, 19, 62, 59, 49, 43, 15, 12, 15, 28, 22, 35, 40, 31, 47, 11, 16, 10, 41, 5, 7, 23, 48, 24, 60, 52, 30, 50, 55, 7) \
+T (168, 49, 27, 41, 40, 42, 20, 39, 50, 17, 58, 9, 54, 2, 38, 48, 16, 62, 43, 18, 59, 22, 63, 29, 61, 60, 6, 33, 24, 14, 57, 4, 28) \
+T (169, 13, 41, 9, 55, 51, 0, 46, 18, 42, 53, 37, 5, 7, 39, 15, 36, 30, 50, 11, 20, 52, 47, 1, 44, 63, 43, 6, 60, 2, 34, 31, 54) \
+T (170, 49, 35, 62, 17, 55, 14, 30, 11, 8, 29, 2, 54, 31, 44, 36, 46, 37, 21, 15, 28, 27, 23, 57, 53, 51, 37, 34, 19, 47, 16, 43, 59) \
+T (171, 50, 37, 40, 26, 46, 58, 54, 59, 17, 30, 23, 11, 43, 61, 31, 8, 60, 34, 25, 63, 4, 41, 39, 48, 51, 13, 49, 22, 52, 57, 29, 13) \
+T (172, 42, 47, 27, 36, 47, 41, 45, 24, 8, 20, 35, 22, 38, 50, 57, 52, 28, 46, 53, 54, 37, 2, 48, 33, 32, 5, 60, 17, 19, 34, 55, 43) \
+T (173, 19, 12, 42, 37, 36, 13, 0, 1, 62, 53, 54, 50, 44, 0, 24, 59, 2, 6, 10, 29, 3, 63, 34, 28, 13, 61, 46, 33, 7, 26, 27, 5) \
+T (174, 32, 5, 30, 54, 15, 26, 25, 28, 1, 51, 11, 39, 2, 30, 27, 13, 43, 6, 7, 25, 31, 8, 3, 16, 41, 29, 26, 5, 19, 58, 42, 59) \
+T (175, 48, 5, 7, 28, 40, 56, 49, 42, 47, 61, 24, 13, 44, 18, 38, 53, 30, 10, 21, 6, 29, 2, 33, 22, 14, 59, 42, 21, 45, 31, 27, 54) \
+T (176, 56, 39, 62, 32, 46, 48, 36, 27, 3, 53, 22, 42, 31, 9, 40, 0, 19, 58, 16, 26, 1, 10, 16, 21, 63, 54, 23, 2, 15, 6, 7, 47) \
+T (177, 31, 18, 57, 52, 5, 32, 56, 7, 11, 6, 9, 20, 30, 56, 46, 23, 42, 38, 3, 34, 19, 45, 21, 55, 0, 8, 53, 24, 29, 60, 25, 49) \
+T (178, 32, 2, 48, 34, 7, 57, 1, 58, 39, 16, 53, 33, 31, 12, 21, 6, 4, 62, 50, 46, 61, 23, 5, 40, 44, 9, 28, 11, 11, 37, 25, 13) \
+T (179, 47, 40, 12, 47, 26, 3, 33, 30, 46, 61, 33, 10, 19, 1, 20, 5, 37, 9, 28, 27, 25, 63, 15, 23, 43, 54, 11, 30, 6, 24, 57, 18) \
+T (180, 16, 27, 2, 62, 63, 52, 26, 21, 37, 18, 41, 45, 15, 9, 51, 46, 28, 38, 60, 30, 35, 20, 7, 52, 53, 24, 42, 56, 33, 22, 48, 31) \
+T (181, 0, 40, 54, 27, 2, 3, 21, 10, 32, 31, 55, 31, 34, 53, 36, 22, 59, 41, 1, 20, 13, 42, 46, 17, 52, 49, 28, 41, 37, 40, 4, 43) \
+T (182, 35, 7, 38, 12, 27, 41, 8, 17, 1, 23, 46, 3, 28, 24, 61, 60, 21, 19, 48, 33, 26, 29, 45, 51, 48, 56, 34, 22, 10, 62, 25, 39) \
+T (183, 61, 14, 56, 62, 44, 59, 54, 26, 61, 27, 52, 24, 3, 33, 12, 16, 48, 47, 28, 9, 21, 38, 23, 0, 55, 5, 22, 39, 9, 35, 59, 63) \
+T (184, 41, 27, 35, 53, 49, 26, 12, 14, 3, 39, 19, 2, 16, 46, 47, 52, 24, 59, 6, 51, 52, 34, 4, 50, 32, 13, 63, 20, 45, 10, 28, 40) \
+T (185, 14, 7, 4, 53, 23, 11, 9, 41, 26, 20, 46, 51, 3, 8, 18, 56, 31, 48, 38, 15, 12, 46, 42, 59, 40, 57, 16, 2, 21, 33, 37, 11) \
+T (186, 46, 10, 6, 33, 7, 2, 37, 4, 11, 32, 59, 60, 2, 4, 12, 47, 26, 39, 27, 52, 5, 58, 30, 24, 36, 55, 63, 28, 62, 25, 43, 25) \
+T (187, 6, 60, 15, 13, 18, 56, 39, 43, 61, 20, 63, 26, 37, 53, 23, 33, 44, 10, 14, 58, 35, 2, 17, 37, 41, 12, 1, 22, 10, 16, 5, 55) \
+T (188, 31, 62, 49, 57, 22, 42, 61, 6, 34, 35, 3, 13, 16, 56, 2, 28, 38, 49, 22, 49, 0, 29, 17, 57, 59, 27, 5, 22, 26, 24, 40, 30) \
+T (189, 3, 24, 42, 30, 19, 13, 9, 57, 6, 46, 36, 52, 16, 55, 60, 4, 2, 50, 32, 33, 58, 15, 22, 33, 21, 39, 20, 37, 27, 0, 1, 53) \
+T (190, 19, 62, 32, 12, 18, 61, 31, 60, 14, 6, 15, 17, 22, 39, 30, 56, 49, 48, 16, 63, 42, 43, 1, 11, 20, 59, 27, 25, 63, 29, 37, 2) \
+T (191, 0, 15, 16, 7, 56, 54, 8, 63, 39, 18, 32, 46, 12, 35, 17, 38, 41, 34, 36, 40, 51, 21, 61, 26, 43, 57, 53, 4, 45, 6, 57, 2) \
+T (192, 52, 12, 62, 8, 60, 56, 29, 5, 6, 7, 9, 21, 44, 47, 48, 53, 58, 54, 45, 40, 15, 17, 1, 28, 4, 55, 22, 57, 32, 19, 33, 10) \
+T (193, 14, 48, 58, 51, 60, 30, 42, 4, 3, 17, 44, 36, 34, 9, 8, 16, 46, 43, 32, 24, 47, 21, 2, 49, 59, 55, 10, 62, 11, 25, 29, 57) \
+T (194, 35, 0, 38, 57, 14, 16, 12, 7, 10, 40, 20, 44, 42, 40, 22, 47, 31, 5, 54, 8, 13, 26, 62, 28, 32, 37, 48, 34, 41, 39, 60, 4) \
+T (195, 30, 15, 1, 38, 55, 58, 7, 14, 13, 12, 11, 35, 17, 22, 39, 32, 50, 13, 5, 62, 51, 63, 46, 10, 8, 61, 9, 49, 59, 4, 0, 34) \
+T (196, 37, 31, 6, 15, 23, 0, 30, 35, 4, 54, 56, 63, 3, 20, 44, 27, 43, 25, 4, 41, 5, 1, 38, 51, 59, 26, 42, 48, 58, 50, 5, 2) \
+T (197, 3, 21, 28, 5, 22, 62, 16, 17, 56, 45, 46, 33, 41, 24, 25, 31, 10, 54, 19, 14, 0, 59, 42, 34, 12, 23, 53, 35, 55, 30, 18, 8) \
+T (198, 3, 56, 16, 31, 45, 6, 37, 26, 34, 41, 36, 52, 21, 48, 13, 27, 22, 51, 62, 60, 59, 0, 25, 62, 44, 9, 23, 42, 11, 33, 39, 57) \
+T (199, 59, 20, 31, 41, 24, 27, 26, 54, 7, 42, 30, 5, 25, 37, 53, 11, 21, 42, 39, 3, 2, 28, 47, 59, 32, 10, 57, 61, 52, 22, 19, 15) \
+T (200, 3, 57, 34, 47, 8, 31, 63, 39, 34, 19, 52, 42, 51, 28, 50, 44, 59, 27, 21, 24, 30, 61, 28, 20, 56, 20, 37, 32, 12, 22, 14, 4) \
+T (201, 1, 61, 23, 43, 21, 38, 13, 42, 45, 40, 24, 16, 59, 4, 46, 11, 43, 10, 30, 55, 20, 5, 49, 62, 22, 31, 54, 21, 53, 36, 17, 8) \
+T (202, 49, 56, 60, 30, 24, 23, 40, 15, 32, 61, 37, 13, 56, 5, 57, 0, 28, 39, 27, 59, 60, 42, 3, 6, 51, 36, 8, 53, 34, 22, 35, 10) \
+T (203, 27, 13, 16, 12, 30, 31, 15, 47, 23, 22, 37, 29, 40, 55, 6, 44, 11, 4, 49, 9, 50, 1, 25, 38, 59, 61, 2, 18, 28, 8, 17, 57) \
+T (204, 5, 62, 5, 37, 27, 2, 31, 25, 9, 40, 58, 34, 60, 17, 14, 0, 8, 47, 44, 43, 21, 54, 15, 20, 57, 35, 30, 61, 36, 7, 16, 32) \
+T (205, 55, 22, 9, 29, 54, 52, 0, 13, 39, 36, 63, 12, 43, 56, 58, 0, 10, 18, 48, 1, 20, 60, 4, 62, 2, 51, 41, 61, 1, 26, 24, 21) \
+T (206, 29, 14, 52, 20, 49, 59, 31, 55, 61, 15, 20, 11, 1, 16, 39, 43, 53, 13, 35, 7, 38, 28, 41, 10, 63, 56, 2, 23, 0, 57, 30, 26) \
+T (207, 31, 45, 56, 4, 19, 1, 32, 44, 20, 50, 8, 39, 58, 33, 59, 29, 62, 3, 55, 11, 28, 6, 32, 29, 43, 41, 7, 5, 18, 15, 21, 14) \
+T (208, 29, 1, 31, 17, 10, 58, 27, 5, 63, 27, 23, 49, 60, 4, 33, 3, 9, 51, 28, 37, 35, 61, 42, 19, 18, 39, 34, 15, 21, 14, 7, 36) \
+T (209, 47, 2, 8, 51, 56, 61, 12, 0, 37, 49, 24, 29, 44, 60, 30, 63, 33, 55, 5, 4, 27, 45, 50, 13, 59, 14, 39, 46, 40, 28, 19, 11) \
+T (210, 50, 2, 52, 36, 3, 59, 4, 24, 20, 41, 8, 49, 48, 5, 28, 37, 22, 18, 26, 16, 61, 38, 43, 33, 30, 16, 6, 42, 55, 54, 14, 32) \
+T (211, 56, 57, 33, 0, 47, 43, 50, 22, 15, 53, 1, 17, 60, 20, 63, 2, 27, 18, 51, 45, 23, 7, 31, 47, 4, 38, 34, 35, 49, 10, 9, 32) \
+T (212, 42, 54, 63, 4, 20, 3, 48, 34, 28, 10, 6, 60, 33, 29, 37, 14, 35, 13, 11, 57, 43, 44, 24, 39, 7, 56, 37, 22, 41, 31, 49, 32) \
+T (213, 40, 25, 61, 33, 60, 4, 1, 28, 29, 63, 47, 56, 9, 6, 22, 39, 7, 16, 38, 55, 18, 10, 34, 3, 24, 59, 9, 51, 44, 35, 14, 47) \
+T (214, 14, 11, 0, 4, 25, 6, 13, 60, 2, 26, 11, 27, 31, 30, 41, 58, 48, 24, 35, 44, 32, 49, 17, 8, 3, 1, 54, 16, 61, 15, 10, 18) \
+T (215, 7, 30, 38, 10, 26, 20, 54, 1, 28, 41, 0, 0, 5, 32, 56, 61, 48, 42, 14, 4, 34, 55, 39, 53, 46, 13, 62, 31, 53, 37, 24, 11) \
+T (216, 43, 36, 2, 21, 0, 28, 16, 53, 23, 7, 47, 30, 37, 28, 6, 35, 40, 60, 50, 32, 60, 9, 32, 46, 55, 49, 29, 13, 22, 14, 8, 62) \
+T (217, 15, 53, 9, 63, 0, 6, 29, 26, 35, 55, 38, 23, 50, 45, 2, 25, 16, 7, 53, 48, 47, 4, 18, 34, 28, 22, 43, 8, 60, 61, 21, 1) \
+T (218, 60, 32, 56, 46, 28, 61, 35, 57, 2, 11, 44, 34, 13, 23, 39, 50, 18, 5, 1, 40, 59, 3, 51, 49, 43, 14, 12, 27, 43, 31, 1, 25) \
+T (219, 4, 10, 19, 21, 46, 37, 30, 61, 45, 45, 40, 59, 39, 18, 42, 50, 2, 3, 23, 15, 32, 26, 52, 31, 35, 38, 48, 53, 20, 6, 12, 57) \
+T (220, 37, 43, 11, 32, 25, 41, 42, 54, 19, 27, 46, 12, 35, 16, 58, 48, 38, 21, 52, 56, 13, 22, 24, 1, 30, 24, 51, 50, 59, 20, 15, 31) \
+T (221, 31, 52, 23, 52, 42, 57, 3, 59, 56, 34, 35, 50, 25, 2, 45, 8, 11, 16, 62, 21, 25, 0, 15, 28, 18, 7, 24, 33, 1, 4, 20, 48) \
+T (222, 2, 37, 10, 34, 16, 28, 56, 57, 42, 11, 0, 27, 60, 25, 23, 61, 44, 36, 55, 53, 62, 41, 13, 27, 24, 20, 14, 39, 19, 8, 50, 56) \
+T (223, 47, 23, 30, 12, 48, 20, 63, 38, 60, 46, 43, 54, 1, 53, 6, 62, 2, 0, 37, 55, 39, 33, 19, 28, 26, 5, 41, 35, 44, 31, 9, 33) \
+T (224, 8, 3, 25, 48, 57, 1, 24, 23, 32, 22, 12, 10, 5, 43, 46, 39, 56, 19, 33, 27, 0, 56, 13, 2, 38, 51, 60, 35, 15, 59, 23, 28) \
+T (225, 15, 40, 34, 53, 58, 22, 7, 47, 54, 5, 33, 13, 60, 17, 52, 45, 24, 20, 36, 16, 61, 21, 46, 56, 23, 2, 42, 63, 43, 59, 57, 9) \
+T (226, 43, 21, 31, 3, 24, 2, 53, 41, 25, 12, 47, 19, 48, 28, 36, 45, 29, 23, 9, 50, 63, 20, 1, 61, 7, 6, 37, 26, 10, 55, 60, 58) \
+T (227, 59, 13, 48, 58, 52, 5, 16, 39, 7, 36, 37, 41, 47, 26, 40, 42, 25, 54, 6, 51, 63, 27, 12, 56, 28, 19, 49, 62, 38, 44, 61, 9)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-4.inc b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc
new file mode 100644
index 00000000000..2044e365dec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc
@@ -0,0 +1,133 @@
+#define N 4
+#define TESTS \
+T (0, 0, 1, 2, 3) \
+T (1, 0, 0, 0, 0) \
+T (2, 6, 3, 1, 5) \
+T (3, 1, 3, 5, 0) \
+T (4, 6, 3, 5, 4) \
+T (5, 6, 4, 1, 0) \
+T (6, 6, 1, 4, 2) \
+T (7, 3, 7, 4, 4) \
+T (8, 3, 2, 4, 4) \
+T (9, 3, 2, 6, 1) \
+T (10, 5, 4, 5, 6) \
+T (11, 1, 4, 0, 7) \
+T (12, 1, 5, 7, 2) \
+T (13, 2, 3, 0, 4) \
+T (14, 7, 6, 4, 2) \
+T (15, 6, 1, 3, 4) \
+T (16, 0, 2, 4, 6) \
+T (17, 1, 3, 5, 7)
+#define EXPTESTS \
+T (116, 1, 2, 4, 3) \
+T (117, 7, 3, 3, 0) \
+T (118, 5, 3, 2, 7) \
+T (119, 0, 3, 5, 6) \
+T (120, 0, 0, 1, 5) \
+T (121, 4, 6, 2, 1) \
+T (122, 2, 5, 6, 3) \
+T (123, 4, 6, 3, 2) \
+T (124, 4, 7, 5, 6) \
+T (125, 0, 4, 2, 4) \
+T (126, 2, 4, 6, 0) \
+T (127, 4, 3, 5, 1) \
+T (128, 5, 4, 7, 3) \
+T (129, 7, 5, 6, 4) \
+T (130, 2, 0, 5, 3) \
+T (131, 7, 4, 3, 0) \
+T (132, 6, 1, 3, 1) \
+T (133, 3, 4, 1, 7) \
+T (134, 0, 0, 6, 4) \
+T (135, 6, 4, 0, 1) \
+T (136, 6, 0, 2, 4) \
+T (137, 1, 3, 4, 2) \
+T (138, 3, 1, 2, 4) \
+T (139, 3, 1, 5, 0) \
+T (140, 1, 6, 0, 2) \
+T (141, 0, 2, 6, 4) \
+T (142, 1, 7, 5, 2) \
+T (143, 7, 0, 4, 1) \
+T (144, 7, 3, 5, 6) \
+T (145, 0, 7, 5, 4) \
+T (146, 6, 4, 2, 3) \
+T (147, 1, 5, 7, 6) \
+T (148, 5, 7, 4, 7) \
+T (149, 5, 2, 2, 0) \
+T (150, 7, 1, 6, 4) \
+T (151, 5, 2, 4, 6) \
+T (152, 5, 0, 4, 6) \
+T (153, 4, 2, 7, 3) \
+T (154, 7, 1, 0, 6) \
+T (155, 0, 4, 2, 5) \
+T (156, 3, 4, 3, 2) \
+T (157, 2, 0, 6, 1) \
+T (158, 5, 1, 7, 4) \
+T (159, 2, 1, 5, 6) \
+T (160, 1, 6, 5, 7) \
+T (161, 2, 4, 1, 6) \
+T (162, 3, 7, 1, 6) \
+T (163, 2, 1, 4, 7) \
+T (164, 4, 2, 1, 0) \
+T (165, 0, 7, 1, 3) \
+T (166, 7, 4, 2, 3) \
+T (167, 4, 5, 3, 5) \
+T (168, 1, 5, 6, 7) \
+T (169, 6, 3, 2, 0) \
+T (170, 6, 2, 1, 5) \
+T (171, 5, 6, 1, 3) \
+T (172, 2, 2, 3, 1) \
+T (173, 5, 4, 3, 5) \
+T (174, 7, 3, 4, 1) \
+T (175, 4, 2, 3, 6) \
+T (176, 7, 6, 5, 3) \
+T (177, 7, 2, 0, 6) \
+T (178, 1, 3, 0, 2) \
+T (179, 5, 3, 0, 5) \
+T (180, 4, 6, 7, 2) \
+T (181, 4, 5, 2, 0) \
+T (182, 5, 0, 1, 2) \
+T (183, 2, 3, 4, 1) \
+T (184, 2, 6, 5, 1) \
+T (185, 0, 6, 7, 4) \
+T (186, 4, 1, 6, 2) \
+T (187, 1, 3, 2, 3) \
+T (188, 2, 5, 4, 3) \
+T (189, 2, 5, 6, 4) \
+T (190, 4, 0, 5, 0) \
+T (191, 2, 1, 6, 0) \
+T (192, 7, 5, 0, 1) \
+T (193, 3, 5, 6, 7) \
+T (194, 0, 1, 2, 7) \
+T (195, 3, 1, 0, 2) \
+T (196, 2, 4, 6, 3) \
+T (197, 6, 0, 5, 4) \
+T (198, 6, 5, 7, 1) \
+T (199, 2, 5, 4, 6) \
+T (200, 7, 2, 3, 6) \
+T (201, 3, 5, 7, 3) \
+T (202, 1, 7, 4, 6) \
+T (203, 4, 0, 7, 1) \
+T (204, 7, 1, 0, 4) \
+T (205, 5, 1, 3, 4) \
+T (206, 0, 7, 3, 5) \
+T (207, 3, 2, 1, 5) \
+T (208, 7, 5, 0, 2) \
+T (209, 7, 0, 6, 3) \
+T (210, 6, 6, 7, 7) \
+T (211, 5, 6, 0, 4) \
+T (212, 5, 1, 2, 2) \
+T (213, 7, 1, 2, 6) \
+T (214, 5, 4, 2, 6) \
+T (215, 1, 5, 6, 4) \
+T (216, 7, 0, 2, 1) \
+T (217, 1, 5, 3, 6) \
+T (218, 3, 3, 6, 5) \
+T (219, 2, 3, 5, 7) \
+T (220, 2, 4, 3, 0) \
+T (221, 1, 5, 6, 3) \
+T (222, 7, 5, 1, 5) \
+T (223, 0, 5, 3, 4) \
+T (224, 2, 3, 1, 4) \
+T (225, 2, 3, 5, 1) \
+T (226, 4, 3, 1, 0) \
+T (227, 2, 3, 5, 5)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-8.inc b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc
new file mode 100644
index 00000000000..24db545ef26
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc
@@ -0,0 +1,133 @@
+#define N 8
+#define TESTS \
+T (0, 0, 1, 2, 3, 4, 5, 6, 7) \
+T (1, 0, 0, 0, 0, 0, 0, 0, 0) \
+T (2, 0, 1, 2, 3, 0, 1, 2, 3) \
+T (3, 0, 10, 3, 8, 1, 11, 10, 2) \
+T (4, 0, 1, 2, 3, 3, 0, 2, 1) \
+T (5, 12, 5, 14, 9, 8, 15, 1, 7) \
+T (6, 9, 10, 11, 8, 4, 15, 14, 12) \
+T (7, 4, 10, 14, 9, 11, 1, 12, 11) \
+T (8, 15, 3, 3, 8, 5, 11, 2, 10) \
+T (9, 13, 11, 10, 15, 8, 5, 14, 8) \
+T (10, 9, 13, 12, 14, 10, 1, 5, 14) \
+T (11, 5, 11, 12, 6, 3, 2, 4, 15) \
+T (12, 5, 13, 14, 8, 4, 10, 4, 12) \
+T (13, 14, 8, 12, 3, 13, 9, 5, 4) \
+T (14, 15, 3, 13, 6, 14, 12, 10, 0) \
+T (15, 0, 5, 11, 7, 4, 6, 14, 1) \
+T (16, 0, 2, 4, 6, 8, 10, 12, 14) \
+T (17, 1, 3, 5, 7, 9, 11, 13, 15)
+#define EXPTESTS \
+T (116, 9, 3, 9, 4, 7, 0, 0, 6) \
+T (117, 4, 14, 12, 8, 9, 6, 0, 10) \
+T (118, 10, 12, 1, 3, 4, 11, 9, 2) \
+T (119, 4, 11, 9, 5, 8, 14, 0, 2) \
+T (120, 0, 10, 8, 6, 4, 9, 7, 5) \
+T (121, 10, 15, 0, 4, 12, 9, 7, 3) \
+T (122, 13, 6, 0, 7, 5, 12, 12, 2) \
+T (123, 4, 10, 11, 15, 12, 7, 3, 8) \
+T (124, 1, 13, 15, 9, 6, 5, 7, 4) \
+T (125, 7, 13, 2, 5, 2, 8, 1, 6) \
+T (126, 4, 5, 2, 12, 14, 13, 8, 6) \
+T (127, 4, 10, 2, 7, 11, 15, 9, 0) \
+T (128, 14, 8, 12, 10, 13, 3, 11, 2) \
+T (129, 10, 8, 14, 9, 5, 1, 15, 7) \
+T (130, 12, 2, 9, 13, 5, 14, 1, 15) \
+T (131, 10, 4, 1, 14, 11, 15, 9, 2) \
+T (132, 9, 12, 7, 4, 2, 1, 0, 9) \
+T (133, 11, 15, 4, 10, 3, 12, 13, 5) \
+T (134, 1, 5, 6, 13, 14, 15, 3, 10) \
+T (135, 0, 14, 6, 10, 1, 13, 3, 2) \
+T (136, 2, 11, 1, 5, 12, 13, 3, 5) \
+T (137, 7, 11, 4, 1, 12, 10, 14, 10) \
+T (138, 3, 6, 7, 13, 11, 15, 10, 0) \
+T (139, 10, 8, 7, 14, 1, 11, 0, 13) \
+T (140, 5, 3, 13, 11, 8, 5, 12, 6) \
+T (141, 15, 2, 12, 13, 10, 8, 5, 0) \
+T (142, 13, 9, 10, 2, 11, 3, 4, 1) \
+T (143, 2, 14, 6, 5, 1, 8, 15, 0) \
+T (144, 12, 9, 14, 10, 1, 3, 11, 13) \
+T (145, 12, 13, 11, 2, 5, 6, 4, 8) \
+T (146, 5, 0, 2, 1, 6, 8, 15, 13) \
+T (147, 8, 7, 1, 3, 5, 11, 14, 15) \
+T (148, 0, 9, 2, 15, 3, 1, 8, 10) \
+T (149, 4, 14, 11, 6, 8, 5, 12, 7) \
+T (150, 5, 9, 10, 12, 14, 15, 2, 7) \
+T (151, 11, 6, 5, 7, 11, 14, 2, 1) \
+T (152, 13, 1, 7, 4, 6, 8, 15, 9) \
+T (153, 10, 12, 9, 1, 6, 7, 8, 15) \
+T (154, 8, 4, 5, 1, 3, 0, 7, 13) \
+T (155, 13, 9, 3, 4, 10, 1, 15, 7) \
+T (156, 13, 8, 2, 7, 0, 6, 3, 6) \
+T (157, 15, 15, 13, 6, 0, 5, 14, 4) \
+T (158, 13, 1, 2, 2, 7, 9, 2, 6) \
+T (159, 5, 12, 10, 13, 6, 1, 4, 7) \
+T (160, 0, 2, 9, 1, 5, 11, 14, 11) \
+T (161, 14, 6, 5, 10, 3, 2, 15, 4) \
+T (162, 3, 10, 0, 1, 13, 14, 11, 15) \
+T (163, 13, 7, 5, 9, 5, 0, 11, 4) \
+T (164, 2, 11, 1, 12, 3, 13, 4, 9) \
+T (165, 1, 0, 10, 11, 5, 13, 4, 3) \
+T (166, 3, 9, 1, 12, 15, 14, 10, 5) \
+T (167, 3, 10, 11, 14, 5, 1, 8, 12) \
+T (168, 10, 15, 5, 14, 4, 13, 6, 3) \
+T (169, 1, 8, 6, 4, 11, 13, 7, 10) \
+T (170, 8, 7, 1, 15, 11, 9, 0, 3) \
+T (171, 4, 0, 11, 7, 1, 15, 3, 13) \
+T (172, 14, 7, 3, 4, 9, 11, 0, 6) \
+T (173, 7, 3, 11, 4, 8, 2, 10, 15) \
+T (174, 7, 9, 14, 2, 0, 5, 13, 3) \
+T (175, 4, 8, 5, 9, 3, 11, 1, 14) \
+T (176, 13, 12, 3, 3, 1, 4, 8, 5) \
+T (177, 7, 12, 9, 13, 10, 4, 5, 8) \
+T (178, 14, 3, 12, 7, 2, 6, 5, 5) \
+T (179, 7, 0, 8, 6, 2, 14, 12, 15) \
+T (180, 2, 12, 0, 4, 1, 15, 11, 10) \
+T (181, 0, 7, 5, 12, 15, 10, 14, 3) \
+T (182, 3, 10, 2, 5, 11, 6, 13, 14) \
+T (183, 3, 2, 7, 11, 0, 13, 8, 10) \
+T (184, 0, 12, 15, 1, 9, 2, 11, 4) \
+T (185, 11, 15, 8, 10, 9, 1, 13, 3) \
+T (186, 12, 13, 15, 12, 3, 9, 5, 7) \
+T (187, 4, 10, 5, 6, 1, 11, 0, 11) \
+T (188, 11, 6, 7, 9, 0, 8, 14, 8) \
+T (189, 1, 15, 6, 9, 12, 6, 7, 14) \
+T (190, 1, 5, 6, 11, 12, 13, 3, 0) \
+T (191, 0, 8, 15, 13, 12, 6, 1, 4) \
+T (192, 12, 15, 8, 4, 2, 0, 9, 5) \
+T (193, 14, 5, 13, 10, 12, 11, 0, 1) \
+T (194, 12, 1, 9, 8, 10, 9, 0, 2) \
+T (195, 11, 0, 13, 4, 6, 2, 14, 15) \
+T (196, 0, 10, 6, 2, 12, 4, 9, 13) \
+T (197, 7, 12, 8, 10, 1, 0, 5, 0) \
+T (198, 12, 13, 0, 5, 3, 14, 11, 4) \
+T (199, 9, 1, 4, 14, 10, 12, 15, 6) \
+T (200, 3, 12, 13, 6, 14, 2, 1, 6) \
+T (201, 5, 14, 8, 10, 1, 12, 2, 0) \
+T (202, 5, 8, 2, 7, 4, 15, 14, 2) \
+T (203, 14, 13, 10, 9, 11, 15, 7, 8) \
+T (204, 12, 13, 14, 2, 4, 9, 5, 7) \
+T (205, 0, 7, 5, 4, 7, 13, 6, 8) \
+T (206, 7, 0, 15, 6, 12, 2, 5, 4) \
+T (207, 8, 6, 0, 1, 1, 11, 1, 9) \
+T (208, 11, 6, 14, 9, 5, 3, 7, 13) \
+T (209, 12, 3, 15, 9, 1, 0, 8, 13) \
+T (210, 11, 1, 9, 8, 7, 6, 12, 2) \
+T (211, 10, 9, 2, 6, 8, 11, 0, 4) \
+T (212, 10, 13, 15, 9, 6, 15, 14, 10) \
+T (213, 9, 5, 8, 3, 4, 7, 11, 4) \
+T (214, 1, 2, 13, 5, 8, 4, 3, 6) \
+T (215, 8, 3, 2, 4, 9, 14, 12, 13) \
+T (216, 5, 7, 8, 15, 3, 1, 10, 4) \
+T (217, 2, 9, 3, 2, 14, 11, 5, 7) \
+T (218, 15, 6, 4, 10, 14, 3, 13, 2) \
+T (219, 0, 8, 14, 5, 15, 7, 10, 1) \
+T (220, 14, 0, 6, 10, 8, 2, 7, 4) \
+T (221, 15, 13, 3, 14, 11, 2, 14, 6) \
+T (222, 8, 2, 10, 13, 1, 0, 4, 11) \
+T (223, 7, 15, 2, 9, 1, 12, 11, 3) \
+T (224, 13, 15, 3, 12, 15, 7, 0, 8) \
+T (225, 0, 2, 1, 11, 14, 3, 9, 14) \
+T (226, 12, 14, 3, 15, 8, 5, 1, 7) \
+T (227, 0, 5, 13, 8, 4, 2, 1, 3)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-main.inc b/gcc/testsuite/gcc.dg/torture/vshuf-main.inc
new file mode 100644
index 00000000000..52b75ee7365
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-main.inc
@@ -0,0 +1,55 @@
+/* Driver fragment for __builtin_shuffle of any vector shape. */
+
+extern void abort (void);
+
+#ifndef UNSUPPORTED
+V a, b, c, d;
+
+#define T(num, msk...) \
+__attribute__((noinline, noclone)) void \
+test_##num (void) \
+{ \
+ VI mask = { msk }; \
+ int i; \
+ c = __builtin_shuffle (a, mask); \
+ d = __builtin_shuffle (a, b, mask); \
+ __asm ("" : : "r" (&c), "r" (&d) : "memory"); \
+ for (i = 0; i < N; ++i) \
+ if (c[i] != a[mask[i] & (N - 1)]) \
+ abort (); \
+ else if ((mask[i] & N)) \
+ { \
+ if (d[i] != b[mask[i] & (N - 1)]) \
+ abort (); \
+ } \
+ else if (d[i] != a[mask[i] & (N - 1)]) \
+ abort (); \
+}
+TESTS
+#ifdef EXPENSIVE
+EXPTESTS
+#endif
+#endif
+
+int
+main ()
+{
+#ifndef UNSUPPORTED
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ a[i] = i + 2;
+ b[i] = N + i + 2;
+ }
+
+#undef T
+#define T(num, msk...) \
+ test_##num ();
+ TESTS
+#ifdef EXPENSIVE
+ EXPTESTS
+#endif
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c
new file mode 100644
index 00000000000..a6fbeb5aed5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned short V __attribute__((vector_size(32)));
+typedef V VI;
+
+#include "vshuf-16.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c
new file mode 100644
index 00000000000..526edf28967
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned char V __attribute__((vector_size(16)));
+typedef V VI;
+
+#include "vshuf-16.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2df.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2df.c
new file mode 100644
index 00000000000..7e327b13b75
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2df.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_DOUBLE__ == 8 && __SIZEOF_LONG_LONG__ == 8
+typedef double V __attribute__((vector_size(16)));
+typedef unsigned long long VI __attribute__((vector_size(16)));
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2di.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2di.c
new file mode 100644
index 00000000000..63da659807b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2di.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_LONG_LONG__ == 8
+typedef unsigned long long V __attribute__((vector_size(16)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c
new file mode 100644
index 00000000000..22bcaa98d57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(8)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(8)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(8)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2si.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2si.c
new file mode 100644
index 00000000000..2138c6ca6f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2si.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(8)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(8)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c
new file mode 100644
index 00000000000..cf85815142a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned char V __attribute__((vector_size(32)));
+typedef V VI;
+
+#include "vshuf-32.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4df.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4df.c
new file mode 100644
index 00000000000..cc9d340a17f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4df.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_DOUBLE__ == 8 && __SIZEOF_LONG_LONG__ == 8
+typedef double V __attribute__((vector_size(32)));
+typedef unsigned long long VI __attribute__((vector_size(32)));
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4di.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4di.c
new file mode 100644
index 00000000000..2d568961641
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4di.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_LONG_LONG__ == 8
+typedef unsigned long long V __attribute__((vector_size(32)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c
new file mode 100644
index 00000000000..cfd56a613ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned short V __attribute__((vector_size(8)));
+typedef V VI;
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c
new file mode 100644
index 00000000000..7e605980312
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(16)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(16)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(16)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4si.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4si.c
new file mode 100644
index 00000000000..f12b98ea209
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4si.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(16)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(16)));
+typedef V VI;
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c
new file mode 100644
index 00000000000..1440fb53f89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned short V __attribute__((vector_size(16)));
+typedef V VI;
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c
new file mode 100644
index 00000000000..4bc96bedc46
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned char V __attribute__((vector_size(8)));
+typedef V VI;
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c
new file mode 100644
index 00000000000..2044760bdc3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(32)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(32)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(32)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8si.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8si.c
new file mode 100644
index 00000000000..dbf9da7a699
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8si.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(32)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(32)));
+typedef V VI;
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c
index 42d4b0dd874..4c3888fd237 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 && j, 0))
+ if (__builtin_expect ((i * i2) > 0 && (j * j2), 0))
g ();
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c
index ff175b975a9..d8f344f7826 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 || j, 0))
+ if (__builtin_expect ((i * i2) > 0 || (j * j2), 0))
;
else
g ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c
index 8fcc4e2bd40..b9e6cfb8ff9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 && j, 0))
+ if (__builtin_expect ((i * i2) > 0 && (j * j2), 0))
a ();
else
b ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c
index 1fecf1b980c..2d2b206683b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 || j, 0))
+ if (__builtin_expect ((i * i2) > 0 || (j * j2), 0))
a ();
else
b ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c
index ed53b287b2a..d0b251db17b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-forwprop" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 && __builtin_expect (j != 0, 1), 0))
+ if (__builtin_expect ((i * i2) > 0 && __builtin_expect ((j * j2) != 0, 1), 0))
a ();
else
b ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/restrict-4.c b/gcc/testsuite/gcc.dg/tree-ssa/restrict-4.c
new file mode 100644
index 00000000000..7bcdcdd053a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/restrict-4.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+foo (int *x, int y)
+{
+ int *__restrict p1 = x;
+ int *__restrict p2 = x + 32;
+ p1[y] = 1;
+ p2[4] = 2;
+ return p1[y];
+}
+
+int
+bar (int *x, int y)
+{
+ int *__restrict p1 = x;
+ int *p3 = x + 32;
+ int *__restrict p2 = p3;
+ p1[y] = 1;
+ p2[4] = 2;
+ return p1[y];
+}
+
+/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" { xfail *-*-* } } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c
new file mode 100644
index 00000000000..daba77d9822
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+#define vector __attribute__((vector_size(16) ))
+
+struct {
+ float i;
+ vector float global_res;
+} s;
+float x;
+int main(int argc)
+{
+ vector float res = (vector float){0.0f,0.0f,0.0f,1.0f};
+ res += (vector float){1.0f,2.0f,3.0f,4.0f};
+ s.global_res = res;
+ x = *((float*)&s.global_res + 1);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Replaced BIT_FIELD_REF.*with 2" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c
new file mode 100644
index 00000000000..b0b54a22865
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+#define vector __attribute__((vector_size(16) ))
+
+struct {
+ float i;
+ vector float global_res;
+} s;
+float foo(float f)
+{
+ vector float res = (vector float){0.0f,f,0.0f,1.0f};
+ s.global_res = res;
+ return *((float*)&s.global_res + 1);
+}
+
+/* { dg-final { scan-tree-dump "Replaced BIT_FIELD_REF.*with f" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-35.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-35.c
new file mode 100644
index 00000000000..dfbd7c1bb48
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-35.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+struct s { _Complex float i; };
+void g(struct s *);
+
+float a1 (float dd)
+{
+ struct s sv;
+ sv.i = dd;
+ float d = __real__ sv.i;
+ g(&sv);
+ return d;
+}
+
+/* { dg-final { scan-tree-dump "Replaced REALPART_EXPR.*with dd" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-36.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-36.c
new file mode 100644
index 00000000000..a8a2dbaadbe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-36.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+extern int opening;
+extern int middle_game;
+int s;
+extern int d[1];
+void PreEvaluate(int wtm)
+{
+ int i, j;
+ if (opening) {
+ d[0]=1;
+ }
+ else if (middle_game) {
+ d[0]=-1;
+ }
+ if (4 != opening) {
+ return;
+ }
+ s = 1;
+}
+
+/* We should be able to CSE the second load of opening. */
+
+/* { dg-final { scan-tree-dump "Replaced opening" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/uninit-B.c b/gcc/testsuite/gcc.dg/uninit-B.c
index f03dd701853..adb1461d951 100644
--- a/gcc/testsuite/gcc.dg/uninit-B.c
+++ b/gcc/testsuite/gcc.dg/uninit-B.c
@@ -9,7 +9,7 @@ void
baz (void)
{
int i;
- if (i) /* { dg-warning "is used uninitialized" "uninit i warning" { xfail *-*-* } } */
+ if (i) /* { dg-warning "is used uninitialized" "uninit i warning" } */
bar (i);
foo (&i);
}
diff --git a/gcc/testsuite/gcc.dg/uninit-pr19430.c b/gcc/testsuite/gcc.dg/uninit-pr19430.c
index 4d2b4f62cef..36129314872 100644
--- a/gcc/testsuite/gcc.dg/uninit-pr19430.c
+++ b/gcc/testsuite/gcc.dg/uninit-pr19430.c
@@ -29,7 +29,7 @@ void frob(int *pi);
int main(void)
{
int i;
- printf("i = %d\n", i); /* { dg-warning "'i' is used uninitialized in this function" "" { xfail *-*-* } } */
+ printf("i = %d\n", i); /* { dg-warning "'i' is used uninitialized in this function" "" } */
frob(&i);
return 0;
@@ -38,6 +38,6 @@ int main(void)
void foo3(int*);
void bar3(void) {
int x;
- if(x) /* { dg-warning "'x' is used uninitialized in this function" "uninitialized" { xfail *-*-* } } */
+ if(x) /* { dg-warning "'x' is used uninitialized in this function" "uninitialized" } */
foo3(&x);
}
diff --git a/gcc/testsuite/gcc.dg/va-arg-4.c b/gcc/testsuite/gcc.dg/va-arg-4.c
new file mode 100644
index 00000000000..6d737c48326
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/va-arg-4.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+#include <stdarg.h>
+extern void baz(...); /* { dg-error "requires a named argument" } */
diff --git a/gcc/testsuite/gcc.dg/va-arg-5.c b/gcc/testsuite/gcc.dg/va-arg-5.c
new file mode 100644
index 00000000000..a00616ee201
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/va-arg-5.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-fallow-parameterless-variadic-functions" } */
+#include <stdarg.h>
+extern void baz(...);
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-29.c b/gcc/testsuite/gcc.dg/vect/bb-slp-29.c
new file mode 100644
index 00000000000..e37b96d14d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-29.c
@@ -0,0 +1,59 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define A 3
+#define B 4
+#define N 256
+
+short src[N], dst[N];
+
+void foo (short * __restrict__ dst, short * __restrict__ src, int h, int stride, int dummy)
+{
+ int i;
+ h /= 16;
+ for (i = 0; i < h; i++)
+ {
+ dst[0] = A*src[0] + B*src[1];
+ dst[1] = A*src[1] + B*src[2];
+ dst[2] = A*src[2] + B*src[3];
+ dst[3] = A*src[3] + B*src[4];
+ dst[4] = A*src[4] + B*src[5];
+ dst[5] = A*src[5] + B*src[6];
+ dst[6] = A*src[6] + B*src[7];
+ dst[7] = A*src[7] + B*src[8];
+ dst += stride;
+ src += stride;
+ if (dummy == 32)
+ abort ();
+ }
+}
+
+
+int main (void)
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ dst[i] = 0;
+ src[i] = i;
+ }
+
+ foo (dst, src, N, 8, 0);
+
+ for (i = 0; i < N/2; i++)
+ {
+ if (dst[i] != A * src[i] + B * src[i+1])
+ abort ();
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target { vect_int_mult && vect_element_align } } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/pr50635.c b/gcc/testsuite/gcc.dg/vect/pr50635.c
new file mode 100644
index 00000000000..6a7ac52e821
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr50635.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+typedef signed long int32_t;
+typedef char int8_t;
+
+void f0a(int32_t * result, int32_t * arg1, int8_t * arg2, int32_t temp_3)
+{
+ int idx;
+ for (idx=0;idx<10;idx += 1)
+ {
+ int32_t temp_4;
+ int32_t temp_12;
+
+ temp_4 = (-2 & arg2[idx]) + temp_3;
+ temp_12 = -2 * arg2[idx] + temp_4;
+ result[idx] = temp_12;
+ }
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/pr50727.c b/gcc/testsuite/gcc.dg/vect/pr50727.c
new file mode 100644
index 00000000000..896b614b9b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr50727.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+typedef unsigned char uint8_t;
+typedef unsigned long uint32_t;
+void
+f0a (uint32_t * __restrict__ result, uint32_t * arg2,
+ uint8_t * __restrict__ arg4)
+{
+ int idx;
+ for (idx = 0; idx < 429; idx += 1)
+ {
+ uint32_t temp_9;
+ uint32_t temp_11;
+ temp_9 = ((-19 | arg4[idx]) >> arg2[idx]);
+ temp_11 = (((-19 ^ arg4[idx]) & arg2[idx]) ^ temp_9);
+ result[idx] = temp_11;
+ }
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c b/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c
index f5e54e71aa0..f53e66d4cee 100644
--- a/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c
+++ b/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c
@@ -19,5 +19,5 @@ int main (int argc, char *argv[]) {
return vidx(short, r1, 0);
}
-/* { dg-final { scan-tree-dump-times ">> k.\[0-9_\]*" 1 "veclower" { target vect_shift_scalar } } } */
-/* { dg-final { cleanup-tree-dump "veclower" } } */
+/* { dg-final { scan-tree-dump-times ">> k.\[0-9_\]*" 1 "veclower2" } } */
+/* { dg-final { cleanup-tree-dump "veclower2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c b/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c
index 0c00c718ef4..4025f6717ae 100644
--- a/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c
+++ b/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c
@@ -17,5 +17,5 @@ int main (int argc, char *argv[]) {
return vidx(short, r1, 0);
}
-/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" { target vect_shift_scalar } } } */
-/* { dg-final { cleanup-tree-dump "veclower" } } */
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower2" } } */
+/* { dg-final { cleanup-tree-dump "veclower2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c b/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c
index 5e79fb58699..677836da90d 100644
--- a/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c
+++ b/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c
@@ -16,5 +16,5 @@ int main (int argc, char *argv[]) {
return vidx(short, r1, 0);
}
-/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" { target vect_shift_scalar } } } */
-/* { dg-final { cleanup-tree-dump "veclower" } } */
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower2" } } */
+/* { dg-final { cleanup-tree-dump "veclower2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-114.c b/gcc/testsuite/gcc.dg/vect/vect-114.c
index 4bc78627815..3d43a7cd4b6 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-114.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-114.c
@@ -34,7 +34,7 @@ int main (void)
return main1 ();
}
-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_perm && vect_hw_misalign } } } } } */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm && vect_hw_misalign } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_perm } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-21.c b/gcc/testsuite/gcc.dg/vect/vect-21.c
index 7a57506a208..28fc72ae737 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-21.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-21.c
@@ -123,7 +123,7 @@ int main (void)
return main1 ();
}
-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target vect_condition } } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-align-2.c b/gcc/testsuite/gcc.dg/vect/vect-align-2.c
index 08a80112d73..293d07b241d 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-align-2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-align-2.c
@@ -15,7 +15,7 @@ struct foo {
} __attribute__ ((packed));
struct foo f2;
-int z[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+int z[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
__attribute__ ((noinline))
void fbar(struct foo *fp)
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-8.c b/gcc/testsuite/gcc.dg/vect/vect-cond-8.c
new file mode 100644
index 00000000000..e5702c25a1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cond-8.c
@@ -0,0 +1,122 @@
+/* { dg-require-effective-target vect_cond_mixed } */
+
+#include "tree-vect.h"
+
+#define N 1024
+float a[N], b[N], c[N];
+int d[N], e[N], f[N];
+unsigned char k[N];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = a[i] < b[i] ? 17 : 0;
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = a[i] < b[i] ? 0 : 24;
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = a[i] < b[i] ? 51 : 12;
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int d2 = d[i], e2 = e[i];
+ f[i] = a[i] < b[i] ? d2 : e2;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ float a2 = a[i], b2 = b[i];
+ c[i] = d[i] < e[i] ? a2 : b2;
+ }
+}
+
+int
+main ()
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ switch (i % 9)
+ {
+ case 0: asm (""); a[i] = - i - 1; b[i] = i + 1; break;
+ case 1: a[i] = 0; b[i] = 0; break;
+ case 2: a[i] = i + 1; b[i] = - i - 1; break;
+ case 3: a[i] = i; b[i] = i + 7; break;
+ case 4: a[i] = i; b[i] = i; break;
+ case 5: a[i] = i + 16; b[i] = i + 3; break;
+ case 6: a[i] = - i - 5; b[i] = - i; break;
+ case 7: a[i] = - i; b[i] = - i; break;
+ case 8: a[i] = - i; b[i] = - i - 7; break;
+ }
+ d[i] = i;
+ e[i] = 2 * i;
+ }
+ f1 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 ? 17 : 0))
+ abort ();
+ f2 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 ? 0 : 24))
+ abort ();
+ f3 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 ? 51 : 12))
+ abort ();
+ f4 ();
+ for (i = 0; i < N; i++)
+ if (f[i] != ((i % 3) == 0 ? d[i] : e[i]))
+ abort ();
+ for (i = 0; i < N; i++)
+ {
+ switch (i % 9)
+ {
+ case 0: asm (""); d[i] = - i - 1; e[i] = i + 1; break;
+ case 1: d[i] = 0; e[i] = 0; break;
+ case 2: d[i] = i + 1; e[i] = - i - 1; break;
+ case 3: d[i] = i; e[i] = i + 7; break;
+ case 4: d[i] = i; e[i] = i; break;
+ case 5: d[i] = i + 16; e[i] = i + 3; break;
+ case 6: d[i] = - i - 5; e[i] = - i; break;
+ case 7: d[i] = - i; e[i] = - i; break;
+ case 8: d[i] = - i; e[i] = - i - 7; break;
+ }
+ a[i] = i;
+ b[i] = i / 2;
+ }
+ f5 ();
+ for (i = 0; i < N; i++)
+ if (c[i] != ((i % 3) == 0 ? a[i] : b[i]))
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops" 5 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-9.c b/gcc/testsuite/gcc.dg/vect/vect-cond-9.c
new file mode 100644
index 00000000000..cfa0363b2fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cond-9.c
@@ -0,0 +1,200 @@
+/* { dg-require-effective-target vect_cond_mixed } */
+
+#include "tree-vect.h"
+
+#define N 1024
+float a[N], b[N], c[N], d[N];
+int j[N];
+unsigned char k[N];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ unsigned int x = a[i] < b[i] ? -1 : 0;
+ unsigned int y = c[i] < d[i] ? -1 : 0;
+ j[i] = (x & y) >> 31;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ j[i] = x & y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ j[i] = (a[i] < b[i]) & (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ k[i] = x & y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = (a[i] < b[i]) & (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ unsigned int x = a[i] < b[i] ? -1 : 0;
+ unsigned int y = c[i] < d[i] ? -1 : 0;
+ j[i] = (x | y) >> 31;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f7 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ j[i] = x | y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f8 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ j[i] = (a[i] < b[i]) | (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f9 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ k[i] = x | y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f10 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = (a[i] < b[i]) | (c[i] < d[i]);
+}
+
+int
+main ()
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ switch (i % 9)
+ {
+ case 0: asm (""); a[i] = - i - 1; b[i] = i + 1; break;
+ case 1: a[i] = 0; b[i] = 0; break;
+ case 2: a[i] = i + 1; b[i] = - i - 1; break;
+ case 3: a[i] = i; b[i] = i + 7; break;
+ case 4: a[i] = i; b[i] = i; break;
+ case 5: a[i] = i + 16; b[i] = i + 3; break;
+ case 6: a[i] = - i - 5; b[i] = - i; break;
+ case 7: a[i] = - i; b[i] = - i; break;
+ case 8: a[i] = - i; b[i] = - i - 7; break;
+ }
+ }
+ for (i = 0; i < N; i++)
+ {
+ switch ((i / 9) % 3)
+ {
+ case 0: c[i] = a[i / 9]; d[i] = b[i / 9]; break;
+ case 1: c[i] = a[i / 9 + 3]; d[i] = b[i / 9 + 3]; break;
+ case 2: c[i] = a[i / 9 + 6]; d[i] = b[i / 9 + 6]; break;
+ }
+ }
+ f1 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f2 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f3 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f4 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+ f5 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+ f6 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f7 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f8 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f9 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+ f10 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops" 10 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c
new file mode 100644
index 00000000000..efee6043707
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c
@@ -0,0 +1,107 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C 16
+
+__attribute__ ((noinline)) void
+foo (short *src, int *dst)
+{
+ int i;
+ short b, b0, b1, b2, b3, *s = src;
+ int *d = dst;
+
+ for (i = 0; i < N/4; i++)
+ {
+ b0 = *s++;
+ b1 = *s++;
+ b2 = *s++;
+ b3 = *s++;
+ *d = b0 << C;
+ d++;
+ *d = b1 << C;
+ d++;
+ *d = b2 << C;
+ d++;
+ *d = b3 << C;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N/4; i++)
+ {
+ b0 = *s++;
+ b1 = *s++;
+ b2 = *s++;
+ b3 = *s++;
+ *d = b0 << C;
+ d++;
+ *d = b1 << C;
+ d++;
+ *d = b2 << C;
+ d++;
+ *d = b3 << 6;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N/4; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ b = *s++;
+ if (*d != b << 6)
+ abort ();
+ d++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ short in[N];
+ int out[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 8 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c
new file mode 100644
index 00000000000..e829a799568
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c
@@ -0,0 +1,58 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C 12
+
+__attribute__ ((noinline)) void
+foo (char *src, int *dst)
+{
+ int i;
+ char b, *s = src;
+ int *d = dst;
+
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ *d = b << C;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ char in[N];
+ int out[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c
new file mode 100644
index 00000000000..75834d481cb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c
@@ -0,0 +1,58 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C 7
+
+__attribute__ ((noinline)) void
+foo (unsigned short *src, unsigned int *dst)
+{
+ int i;
+ unsigned short b, *s = src;
+ unsigned int *d = dst;
+
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ *d = b << C;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ unsigned short in[N];
+ unsigned int out[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c
new file mode 100644
index 00000000000..b87a277c2f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c
@@ -0,0 +1,65 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C1 10
+#define C2 5
+
+__attribute__ ((noinline)) void
+foo (unsigned char *src, unsigned int *dst1, unsigned int *dst2)
+{
+ int i;
+ unsigned char b, *s = src;
+ unsigned int *d1 = dst1, *d2 = dst2;
+
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ *d1 = b << C1;
+ d1++;
+ *d2 = b << C2;
+ d2++;
+ }
+
+ s = src;
+ d1 = dst1;
+ d2 = dst2;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d1 != b << C1 || *d2 != b << C2)
+ abort ();
+ d1++;
+ d2++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ unsigned char in[N];
+ unsigned int out1[N];
+ unsigned int out2[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out1[i] = 255;
+ out2[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out1, out2);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp
index 8f57f29ad09..b8a41cc16f9 100644
--- a/gcc/testsuite/gcc.dg/vect/vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/vect.exp
@@ -39,15 +39,15 @@ if ![check_vect_support_and_set_flags] {
return
}
-global VEC_FLAGS
-set VEC_FLAGS $DEFAULT_VECTCFLAGS
-
# These flags are used for all targets.
lappend DEFAULT_VECTCFLAGS "-ftree-vectorize" "-fno-vect-cost-model"
# Initialize `dg'.
dg-init
+global VEC_FLAGS
+set VEC_FLAGS $DEFAULT_VECTCFLAGS
+
global O1_VECTCFLAGS
set O1_VECTCFLAGS $DEFAULT_VECTCFLAGS
lappend O1_VECTCFLAGS "-O1"
@@ -64,8 +64,8 @@ lappend DEFAULT_VECTCFLAGS "-O2"
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/nodump-*.\[cS\]]] \
"" $DEFAULT_VECTCFLAGS
-# "-O -fdump-tree-veclower"
-lappend VEC_FLAGS "-O" "-fdump-tree-veclower"
+# "-O -fdump-tree-veclower2"
+lappend VEC_FLAGS "-O" "-fdump-tree-veclower2"
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vec-scal-*.\[cS\]]] \
"" $VEC_FLAGS
diff --git a/gcc/testsuite/gcc.dg/vla-23.c b/gcc/testsuite/gcc.dg/vla-23.c
new file mode 100644
index 00000000000..47be4123301
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-23.c
@@ -0,0 +1,17 @@
+/* PR rtl-optimization/50615 */
+/* Testcase by Zdenek Sojka <zsojka@seznam.cz> */
+
+/* { dg-do compile } */
+/* { dg-options "-O --param max-cse-insns=1" } */
+
+int
+foo (int a)
+{
+ if (!a)
+ return 1;
+
+ {
+ int s[a];
+ return 0;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c
new file mode 100644
index 00000000000..19342bf80dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v5_ok } */
+/* { dg-options "-std=gnu99" } */
+/* { dg-add-options arm_arch_v5 } */
+/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
+
+#include "../../gcc.dg/di-longlong64-sync-1.c"
+
+/* On an old ARM we have no ldrexd or strexd so we have to use helpers. */
+/* { dg-final { scan-assembler-not "ldrexd" } } */
+/* { dg-final { scan-assembler-not "strexd" } } */
+/* { dg-final { scan-assembler "__sync_" } } */
diff --git a/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c
new file mode 100644
index 00000000000..dab69405ef4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arm_ok } */
+/* { dg-options "-marm -std=gnu99" } */
+/* { dg-require-effective-target arm_arch_v6k_ok } */
+/* { dg-add-options arm_arch_v6k } */
+/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
+
+#include "../../gcc.dg/di-longlong64-sync-1.c"
+
+/* We should be using ldrexd, strexd and no helpers or shorter ldrex. */
+/* { dg-final { scan-assembler-times "\tldrexd" 46 } } */
+/* { dg-final { scan-assembler-times "\tstrexd" 46 } } */
+/* { dg-final { scan-assembler-not "__sync_" } } */
+/* { dg-final { scan-assembler-not "ldrex\t" } } */
+/* { dg-final { scan-assembler-not "strex\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr50305.c b/gcc/testsuite/gcc.target/arm/pr50305.c
new file mode 100644
index 00000000000..2f6ad5cfeab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr50305.c
@@ -0,0 +1,60 @@
+/* { dg-do compile } */
+/* { dg-skip-if "incompatible options" { arm*-*-* } { "-march=*" } { "-march=armv7-a" } } */
+/* { dg-options "-O2 -fno-omit-frame-pointer -marm -march=armv7-a -mfpu=vfp3" } */
+
+struct event {
+ unsigned long long id;
+ unsigned int flag;
+};
+
+void dummy(void)
+{
+ /* This is here to ensure that the offset of perf_event_id below
+ relative to the LANCHOR symbol exceeds the allowed displacement. */
+ static int __warned[300];
+ __warned[0] = 1;
+}
+
+extern void *kmem_cache_alloc_trace (void *cachep);
+extern void *cs_cachep;
+extern int nr_cpu_ids;
+
+struct event *
+event_alloc (int cpu)
+{
+ static unsigned long long __attribute__((aligned(8))) perf_event_id;
+ struct event *event;
+ unsigned long long result;
+ unsigned long tmp;
+
+ if (cpu >= nr_cpu_ids)
+ return 0;
+
+ event = kmem_cache_alloc_trace (cs_cachep);
+
+ __asm__ __volatile__ ("dmb" : : : "memory");
+
+ __asm__ __volatile__("@ atomic64_add_return\n"
+"1: ldrexd %0, %H0, [%3]\n"
+" adds %0, %0, %4\n"
+" adc %H0, %H0, %H4\n"
+" strexd %1, %0, %H0, [%3]\n"
+" teq %1, #0\n"
+" bne 1b"
+ : "=&r" (result), "=&r" (tmp), "+Qo" (perf_event_id)
+ : "r" (&perf_event_id), "r" (1LL)
+ : "cc");
+
+ __asm__ __volatile__ ("dmb" : : : "memory");
+
+ event->id = result;
+
+ if (cpu)
+ event->flag = 1;
+
+ for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+ kmem_cache_alloc_trace (cs_cachep);
+
+ return event;
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/shiftable.c b/gcc/testsuite/gcc.target/arm/shiftable.c
new file mode 100644
index 00000000000..f3080620a9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/shiftable.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target arm32 } */
+
+/* ARM has shift-and-alu insns. Depending on the ALU op GCC represents some
+ of these as a left shift, others as a multiply. Check that we match the
+ right one. */
+
+int
+plus (int a, int b)
+{
+ return (a * 64) + b;
+}
+
+/* { dg-final { scan-assembler "add.*\[al]sl #6" } } */
+
+int
+minus (int a, int b)
+{
+ return a - (b * 64);
+}
+
+/* { dg-final { scan-assembler "sub.*\[al]sl #6" } } */
+
+int
+ior (int a, int b)
+{
+ return (a * 64) | b;
+}
+
+/* { dg-final { scan-assembler "orr.*\[al]sl #6" } } */
+
+int
+xor (int a, int b)
+{
+ return (a * 64) ^ b;
+}
+
+/* { dg-final { scan-assembler "eor.*\[al]sl #6" } } */
+
+int
+and (int a, int b)
+{
+ return (a * 64) & b;
+}
+
+/* { dg-final { scan-assembler "and.*\[al]sl #6" } } */
+
+int
+rsb (int a, int b)
+{
+ return (a * 64) - b;
+}
+
+/* { dg-final { scan-assembler "rsb.*\[al]sl #6" } } */
+
+int
+mvn (int a, int b)
+{
+ return ~(a * 64);
+}
+
+/* { dg-final { scan-assembler "mvn.*\[al]sl #6" } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c
new file mode 100644
index 00000000000..c4f56404225
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+void unknown_alignment (char *dest, char *src)
+{
+ memcpy (dest, src, 15);
+}
+
+/* We should see three unaligned word loads and store pairs, one unaligned
+ ldrh/strh pair, and an ldrb/strb pair. Sanity check that. */
+
+/* { dg-final { scan-assembler-times "@ unaligned" 8 } } */
+/* { dg-final { scan-assembler-times "ldrh" 1 } } */
+/* { dg-final { scan-assembler-times "strh" 1 } } */
+/* { dg-final { scan-assembler-times "ldrb" 1 } } */
+/* { dg-final { scan-assembler-times "strb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c
new file mode 100644
index 00000000000..c7d24c9c5c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+char dest[16];
+
+void aligned_dest (char *src)
+{
+ memcpy (dest, src, 15);
+}
+
+/* Expect a multi-word store for the main part of the copy, but subword
+ loads/stores for the remainder. */
+
+/* { dg-final { scan-assembler-times "stmia" 1 } } */
+/* { dg-final { scan-assembler-times "ldrh" 1 } } */
+/* { dg-final { scan-assembler-times "strh" 1 } } */
+/* { dg-final { scan-assembler-times "ldrb" 1 } } */
+/* { dg-final { scan-assembler-times "strb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c
new file mode 100644
index 00000000000..5f0413738c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+char src[16];
+
+void aligned_src (char *dest)
+{
+ memcpy (dest, src, 15);
+}
+
+/* Expect a multi-word load for the main part of the copy, but subword
+ loads/stores for the remainder. */
+
+/* { dg-final { scan-assembler-times "ldmia" 1 } } */
+/* { dg-final { scan-assembler-times "ldrh" 1 } } */
+/* { dg-final { scan-assembler-times "strh" 1 } } */
+/* { dg-final { scan-assembler-times "ldrb" 1 } } */
+/* { dg-final { scan-assembler-times "strb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c
new file mode 100644
index 00000000000..99957086e7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+char src[16];
+char dest[16];
+
+void aligned_both (void)
+{
+ memcpy (dest, src, 15);
+}
+
+/* We know both src and dest to be aligned: expect multiword loads/stores. */
+
+/* { dg-final { scan-assembler-times "ldmia" 1 } } */
+/* { dg-final { scan-assembler-times "stmia" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/wmul-12.c b/gcc/testsuite/gcc.target/arm/wmul-12.c
index 556e53f8e44..5c6b5b9882c 100644
--- a/gcc/testsuite/gcc.target/arm/wmul-12.c
+++ b/gcc/testsuite/gcc.target/arm/wmul-12.c
@@ -5,8 +5,8 @@
long long
foo (int *b, int *c)
{
- int tmp = *b * *c;
- return 10 + (long long)tmp;
+ long long tmp = (long long)*b * *c;
+ return 10 + tmp;
}
/* { dg-final { scan-assembler "smlal" } } */
diff --git a/gcc/testsuite/gcc.target/arm/wmul-8.c b/gcc/testsuite/gcc.target/arm/wmul-8.c
index 3de065d0a62..5ae110d3c49 100644
--- a/gcc/testsuite/gcc.target/arm/wmul-8.c
+++ b/gcc/testsuite/gcc.target/arm/wmul-8.c
@@ -5,7 +5,7 @@
long long
foo (long long a, int *b, int *c)
{
- return a + *b * *c;
+ return a + (long long)*b * *c;
}
/* { dg-final { scan-assembler "smlal" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-mul-1.c b/gcc/testsuite/gcc.target/i386/avx-mul-1.c
new file mode 100644
index 00000000000..0d511c95cb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx } */
+/* { dg-options "-O3 -mavx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c
new file mode 100644
index 00000000000..3ae122c7e88
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx } */
+/* { dg-options "-O3 -mavx -mno-avx2" } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-phminposuw-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c
new file mode 100644
index 00000000000..4a37ba542ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx -mno-avx2" } */
+
+#include "avx-vphminposuw-2.c"
+
+/* { dg-final { scan-assembler "vphminposuw\[^\n\r\]*xmm" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-mul-1.c b/gcc/testsuite/gcc.target/i386/avx2-mul-1.c
new file mode 100644
index 00000000000..0351fbb7c3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-options "-O3 -mavx2" } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx2_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c
new file mode 100644
index 00000000000..238f0209218
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE char
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddb\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c
new file mode 100644
index 00000000000..c57ef8fea30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE int
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c
new file mode 100644
index 00000000000..801bd39d82f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE long long int
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c
new file mode 100644
index 00000000000..facee9f2d57
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpand-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpand-3.c
new file mode 100644
index 00000000000..67ca4a7cda1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpand-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned
+#define BIN_OP(a, b) ((a) & (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpand\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c
new file mode 100644
index 00000000000..b2d539ba49a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE int
+#define BIN_OP(a, b) ((a) * (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpmulld\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c
new file mode 100644
index 00000000000..46d173fc371
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define BIN_OP(a, b) ((a) * (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpmullw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpop-check.h b/gcc/testsuite/gcc.target/i386/avx2-vpop-check.h
new file mode 100644
index 00000000000..143b54dae03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpop-check.h
@@ -0,0 +1,53 @@
+#include "avx2-check.h"
+
+#define SIZE 256
+
+TYPE a[SIZE];
+TYPE b[SIZE];
+TYPE c[SIZE];
+volatile TYPE c_ref[SIZE];
+
+__attribute__ ((__noinline__))
+void
+gen_pop ()
+{
+ int i;
+ for (i = 0; i < SIZE; ++i)
+#ifdef BIN_OP
+ c[i] = BIN_OP (a[i], b[i]);
+#else /* Must be UN_OP */
+ c[i] = UN_OP (a[i]);
+#endif /* BIN_OP */
+}
+
+void
+check_pop ()
+{
+ int i;
+ for (i = 0; i < SIZE; ++i)
+#ifdef BIN_OP
+ c_ref[i] = BIN_OP (a[i], b[i]);
+#else /* Must be UN_OP */
+ c_ref[i] = UN_OP (a[i]);
+#endif /* BIN_OP */
+}
+
+void static
+avx2_test (void)
+{
+ int i, j;
+ for (i = 0; i < 4; ++i )
+ {
+ for ( j = 0; j < SIZE; ++j )
+ {
+ a[i] = i * i + i;
+ b[i] = i * i * i;
+ }
+
+ gen_pop ();
+ check_pop ();
+
+ if (memcmp (c, c_ref, SIZE * sizeof (TYPE)))
+ abort();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c
new file mode 100644
index 00000000000..97affb4bb7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsrld\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c
new file mode 100644
index 00000000000..e7112565b3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsraw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c
new file mode 100644
index 00000000000..97affb4bb7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsrld\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c
new file mode 100644
index 00000000000..67f3afc4131
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned short
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsrlw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c
new file mode 100644
index 00000000000..843128b4f27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE char
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubb\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c
new file mode 100644
index 00000000000..f8f399f6b00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE int
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c
new file mode 100644
index 00000000000..0a23a280e52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE long long int
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c
new file mode 100644
index 00000000000..1cb90b5a8e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
index 7d188e2b466..f1d79793ff8 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
@@ -26,4 +26,4 @@ avx_test (void)
/* { dg-final { scan-assembler-not "\\*avx_movdqu256/1" } } */
/* { dg-final { scan-assembler "\\*sse2_movdqu/1" } } */
-/* { dg-final { scan-assembler "vinsertf128" } } */
+/* { dg-final { scan-assembler "vinsert.128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
index 670305423fe..fe362480b60 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-load" } */
+/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-load -mtune=generic" } */
#define N 1024
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
index d8ae5a90189..3339cc5e703 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
@@ -26,4 +26,4 @@ avx_test (void)
/* { dg-final { scan-assembler-not "\\*avx_movdqu256/2" } } */
/* { dg-final { scan-assembler "vmovdqu.*\\*movv16qi_internal/3" } } */
-/* { dg-final { scan-assembler "vextractf128" } } */
+/* { dg-final { scan-assembler "vextract.128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
index 65e820444e4..8ecd363348e 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store" } */
+/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -mtune=generic" } */
#define N 1024
diff --git a/gcc/testsuite/gcc.target/i386/fma_1.h b/gcc/testsuite/gcc.target/i386/fma_1.h
new file mode 100644
index 00000000000..72d7373946f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_1.h
@@ -0,0 +1,101 @@
+
+#ifndef fma_1
+#define fma_1
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * a - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * a - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * a - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * a - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * a - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * a - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * a - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * a + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * a - b;
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_2.h b/gcc/testsuite/gcc.target/i386/fma_2.h
new file mode 100644
index 00000000000..c5d38d19a1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_2.h
@@ -0,0 +1,101 @@
+
+#ifndef fma_2
+#define fma_2
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * a - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * a - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * a - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * a - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * a - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * a - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * a - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * a + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * a - c;
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_3.h b/gcc/testsuite/gcc.target/i386/fma_3.h
new file mode 100644
index 00000000000..efa88b5d977
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_3.h
@@ -0,0 +1,101 @@
+
+#ifndef fma_3
+#define fma_3
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * b - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * b - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * b - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * b - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * b - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * b - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * b - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * b + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * b - a;
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_4.h b/gcc/testsuite/gcc.target/i386/fma_4.h
new file mode 100644
index 00000000000..9fbb3efdf1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_4.h
@@ -0,0 +1,101 @@
+
+#ifndef fma_4
+#define fma_4
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * b - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * b - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * b - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * b - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * b - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * b - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * b - c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * b + c;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * b - c;
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_5.h b/gcc/testsuite/gcc.target/i386/fma_5.h
new file mode 100644
index 00000000000..3409db8f4fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_5.h
@@ -0,0 +1,101 @@
+
+#ifndef fma_5
+#define fma_5
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * c - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * c - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * c - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * c - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * c - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * c - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * c - a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * c + a;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * c - a;
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_6.h b/gcc/testsuite/gcc.target/i386/fma_6.h
new file mode 100644
index 00000000000..a6bb4b0cd81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_6.h
@@ -0,0 +1,101 @@
+
+#ifndef fma_6
+#define fma_6
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) + c) * c - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) + c) * c - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return ((a * b) - c) * c - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -((a * b) - c) * c - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) + c) * c - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) + c) * c - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return (-(a * b) - c) * c - b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * c + b;
+}
+
+TYPE __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE a, TYPE b, TYPE c)
+{
+ return -(-(a * b) - c) * c - b;
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_1.c b/gcc/testsuite/gcc.target/i386/fma_double_1.c
new file mode 100644
index 00000000000..c3aa3e83c02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_double_1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_1.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231sd" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_2.c b/gcc/testsuite/gcc.target/i386/fma_double_2.c
new file mode 100644
index 00000000000..843eff0a158
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_double_2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_2.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_3.c b/gcc/testsuite/gcc.target/i386/fma_double_3.c
new file mode 100644
index 00000000000..ac69684fee0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_double_3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_3.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231sd" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_4.c b/gcc/testsuite/gcc.target/i386/fma_double_4.c
new file mode 100644
index 00000000000..51fc111adb2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_double_4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_4.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_5.c b/gcc/testsuite/gcc.target/i386/fma_double_5.c
new file mode 100644
index 00000000000..3eca38c1494
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_double_5.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_5.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_6.c b/gcc/testsuite/gcc.target/i386/fma_double_6.c
new file mode 100644
index 00000000000..7b75a224f11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_double_6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_6.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_1.c b/gcc/testsuite/gcc.target/i386/fma_float_1.c
new file mode 100644
index 00000000000..67b1f3fe7cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_float_1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_1.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ss" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_2.c b/gcc/testsuite/gcc.target/i386/fma_float_2.c
new file mode 100644
index 00000000000..a54644d0c70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_float_2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_2.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_3.c b/gcc/testsuite/gcc.target/i386/fma_float_3.c
new file mode 100644
index 00000000000..afb88b60745
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_float_3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_3.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ss" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_4.c b/gcc/testsuite/gcc.target/i386/fma_float_4.c
new file mode 100644
index 00000000000..d9689d9a7af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_float_4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_4.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_5.c b/gcc/testsuite/gcc.target/i386/fma_float_5.c
new file mode 100644
index 00000000000..cb067ca4a91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_float_5.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_5.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_6.c b/gcc/testsuite/gcc.target/i386/fma_float_6.c
new file mode 100644
index 00000000000..c7580736834
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_float_6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_6.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_main.h b/gcc/testsuite/gcc.target/i386/fma_main.h
new file mode 100644
index 00000000000..24464ab508b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_main.h
@@ -0,0 +1,117 @@
+
+#ifndef fma_main
+#define fma_main
+
+#if DEBUG
+#include <stdio.h>
+#endif
+
+TYPE m1[32] = {
+ 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
+ };
+TYPE m2[32] = {
+ 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
+ };
+TYPE m3[32] = {
+ 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
+ };
+TYPE m4[32];
+int test_fails = 0;
+
+void
+compare_result(char * title, TYPE *res)
+{
+ int i;
+ int good = 1;
+ for (i =0; i < 32; i++)
+ if (m4[i] != res[i])
+ {
+ if (good)
+ {
+#if DEBUG
+ printf ("!!!! %s miscompare\n", title);
+#endif
+ good = 0;
+ }
+#if DEBUG
+ printf ("res[%d] = %d, must be %d\n", i, (int)res[i], (int) m4[i]);
+#endif
+ }
+ if (!good)
+ test_fails = 1;
+}
+
+static void fma_test ()
+{
+ int i;
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_add_noneg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test0000", res_test0000);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_add_noneg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test0001", res_test0001);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_add_neg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test0010", res_test0010);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_add_neg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test0011", res_test0011);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_sub_noneg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test0100", res_test0100);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_sub_noneg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test0101", res_test0101);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_sub_neg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test0110", res_test0110);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_noneg_sub_neg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test0111", res_test0111);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_add_noneg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test1000", res_test1000);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_add_noneg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test1001", res_test1001);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_add_neg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test1010", res_test1010);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_add_neg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test1011", res_test1011);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_sub_noneg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test1100", res_test1100);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_sub_noneg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test1101", res_test1101);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_sub_neg_add (m1[i], m2[i], m3[i]);
+ compare_result ("test1110", res_test1110);
+
+ for (i=0; i <32; i++)
+ m4[i] = test_neg_sub_neg_sub (m1[i], m2[i], m3[i]);
+ compare_result ("test1111", res_test1111);
+
+ if (test_fails) abort ();
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_1.c b/gcc/testsuite/gcc.target/i386/fma_run_double_1.c
new file mode 100644
index 00000000000..a2f2aae9e14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_1.h"
+
+#include "fma_run_double_results_1.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_2.c b/gcc/testsuite/gcc.target/i386/fma_run_double_2.c
new file mode 100644
index 00000000000..a389473a894
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_2.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_2.h"
+
+#include "fma_run_double_results_2.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_3.c b/gcc/testsuite/gcc.target/i386/fma_run_double_3.c
new file mode 100644
index 00000000000..7b9d6273bac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_3.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_3.h"
+
+#include "fma_run_double_results_3.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_4.c b/gcc/testsuite/gcc.target/i386/fma_run_double_4.c
new file mode 100644
index 00000000000..1c0456dbad8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_4.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_4.h"
+
+#include "fma_run_double_results_4.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_5.c b/gcc/testsuite/gcc.target/i386/fma_run_double_5.c
new file mode 100644
index 00000000000..6c09f0bb8a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_5.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_5.h"
+
+#include "fma_run_double_results_5.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_6.c b/gcc/testsuite/gcc.target/i386/fma_run_double_6.c
new file mode 100644
index 00000000000..32e51bf3197
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_6.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "fma_6.h"
+
+#include "fma_run_double_results_6.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_results_1.h b/gcc/testsuite/gcc.target/i386/fma_run_double_results_1.h
new file mode 100644
index 00000000000..27f325b86bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_results_1.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_double_results_1
+#define fma_run_double_results_1
+
+TYPE res_test0000[32] = {
+ 7, 23, 55, 109, 191, 307, 463, 665, 919, 1231, 1607, 2053, 2575, 3179, 3871, 4657, 5543, 6535, 7639, 8861, 10207, 11683, 13295, 15049, 16951, 19007, 21223, 23605, 26159, 28891, 31807, 34913
+};
+TYPE res_test0001[32] = {
+ 3, 17, 47, 99, 179, 293, 447, 647, 899, 1209, 1583, 2027, 2547, 3149, 3839, 4623, 5507, 6497, 7599, 8819, 10163, 11637, 13247, 14999, 16899, 18953, 21167, 23547, 26099, 28829, 31743, 34847
+};
+TYPE res_test0010[32] = {
+ -3, -17, -47, -99, -179, -293, -447, -647, -899, -1209, -1583, -2027, -2547, -3149, -3839, -4623, -5507, -6497, -7599, -8819, -10163, -11637, -13247, -14999, -16899, -18953, -21167, -23547, -26099, -28829, -31743, -34847
+};
+TYPE res_test0011[32] = {
+ -7, -23, -55, -109, -191, -307, -463, -665, -919, -1231, -1607, -2053, -2575, -3179, -3871, -4657, -5543, -6535, -7639, -8861, -10207, -11683, -13295, -15049, -16951, -19007, -21223, -23605, -26159, -28891, -31807, -34913
+};
+TYPE res_test0100[32] = {
+ 1, 7, 25, 61, 121, 211, 337, 505, 721, 991, 1321, 1717, 2185, 2731, 3361, 4081, 4897, 5815, 6841, 7981, 9241, 10627, 12145, 13801, 15601, 17551, 19657, 21925, 24361, 26971, 29761, 32737
+};
+TYPE res_test0101[32] = {
+ -3, 1, 17, 51, 109, 197, 321, 487, 701, 969, 1297, 1691, 2157, 2701, 3329, 4047, 4861, 5777, 6801, 7939, 9197, 10581, 12097, 13751, 15549, 17497, 19601, 21867, 24301, 26909, 29697, 32671
+};
+TYPE res_test0110[32] = {
+ 3, -1, -17, -51, -109, -197, -321, -487, -701, -969, -1297, -1691, -2157, -2701, -3329, -4047, -4861, -5777, -6801, -7939, -9197, -10581, -12097, -13751, -15549, -17497, -19601, -21867, -24301, -26909, -29697, -32671
+};
+TYPE res_test0111[32] = {
+ -1, -7, -25, -61, -121, -211, -337, -505, -721, -991, -1321, -1717, -2185, -2731, -3361, -4081, -4897, -5815, -6841, -7981, -9241, -10627, -12145, -13801, -15601, -17551, -19657, -21925, -24361, -26971, -29761, -32737
+};
+TYPE res_test1000[32] = {
+ 3, -1, -17, -51, -109, -197, -321, -487, -701, -969, -1297, -1691, -2157, -2701, -3329, -4047, -4861, -5777, -6801, -7939, -9197, -10581, -12097, -13751, -15549, -17497, -19601, -21867, -24301, -26909, -29697, -32671
+};
+TYPE res_test1001[32] = {
+ -1, -7, -25, -61, -121, -211, -337, -505, -721, -991, -1321, -1717, -2185, -2731, -3361, -4081, -4897, -5815, -6841, -7981, -9241, -10627, -12145, -13801, -15601, -17551, -19657, -21925, -24361, -26971, -29761, -32737
+};
+TYPE res_test1010[32] = {
+ 1, 7, 25, 61, 121, 211, 337, 505, 721, 991, 1321, 1717, 2185, 2731, 3361, 4081, 4897, 5815, 6841, 7981, 9241, 10627, 12145, 13801, 15601, 17551, 19657, 21925, 24361, 26971, 29761, 32737
+};
+TYPE res_test1011[32] = {
+ -3, 1, 17, 51, 109, 197, 321, 487, 701, 969, 1297, 1691, 2157, 2701, 3329, 4047, 4861, 5777, 6801, 7939, 9197, 10581, 12097, 13751, 15549, 17497, 19601, 21867, 24301, 26909, 29697, 32671
+};
+TYPE res_test1100[32] = {
+ -3, -17, -47, -99, -179, -293, -447, -647, -899, -1209, -1583, -2027, -2547, -3149, -3839, -4623, -5507, -6497, -7599, -8819, -10163, -11637, -13247, -14999, -16899, -18953, -21167, -23547, -26099, -28829, -31743, -34847
+};
+TYPE res_test1101[32] = {
+ -7, -23, -55, -109, -191, -307, -463, -665, -919, -1231, -1607, -2053, -2575, -3179, -3871, -4657, -5543, -6535, -7639, -8861, -10207, -11683, -13295, -15049, -16951, -19007, -21223, -23605, -26159, -28891, -31807, -34913
+};
+TYPE res_test1110[32] = {
+ 7, 23, 55, 109, 191, 307, 463, 665, 919, 1231, 1607, 2053, 2575, 3179, 3871, 4657, 5543, 6535, 7639, 8861, 10207, 11683, 13295, 15049, 16951, 19007, 21223, 23605, 26159, 28891, 31807, 34913
+};
+TYPE res_test1111[32] = {
+ 3, 17, 47, 99, 179, 293, 447, 647, 899, 1209, 1583, 2027, 2547, 3149, 3839, 4623, 5507, 6497, 7599, 8819, 10163, 11637, 13247, 14999, 16899, 18953, 21167, 23547, 26099, 28829, 31743, 34847
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_results_2.h b/gcc/testsuite/gcc.target/i386/fma_run_double_results_2.h
new file mode 100644
index 00000000000..f9327ce6501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_results_2.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_double_results_2
+#define fma_run_double_results_2
+
+TYPE res_test0000[32] = {
+ 8, 24, 56, 110, 192, 308, 464, 666, 920, 1232, 1608, 2054, 2576, 3180, 3872, 4658, 5544, 6536, 7640, 8862, 10208, 11684, 13296, 15050, 16952, 19008, 21224, 23606, 26160, 28892, 31808, 34914
+};
+TYPE res_test0001[32] = {
+ 2, 16, 46, 98, 178, 292, 446, 646, 898, 1208, 1582, 2026, 2546, 3148, 3838, 4622, 5506, 6496, 7598, 8818, 10162, 11636, 13246, 14998, 16898, 18952, 21166, 23546, 26098, 28828, 31742, 34846
+};
+TYPE res_test0010[32] = {
+ -2, -16, -46, -98, -178, -292, -446, -646, -898, -1208, -1582, -2026, -2546, -3148, -3838, -4622, -5506, -6496, -7598, -8818, -10162, -11636, -13246, -14998, -16898, -18952, -21166, -23546, -26098, -28828, -31742, -34846
+};
+TYPE res_test0011[32] = {
+ -8, -24, -56, -110, -192, -308, -464, -666, -920, -1232, -1608, -2054, -2576, -3180, -3872, -4658, -5544, -6536, -7640, -8862, -10208, -11684, -13296, -15050, -16952, -19008, -21224, -23606, -26160, -28892, -31808, -34914
+};
+TYPE res_test0100[32] = {
+ 2, 8, 26, 62, 122, 212, 338, 506, 722, 992, 1322, 1718, 2186, 2732, 3362, 4082, 4898, 5816, 6842, 7982, 9242, 10628, 12146, 13802, 15602, 17552, 19658, 21926, 24362, 26972, 29762, 32738
+};
+TYPE res_test0101[32] = {
+ -4, 0, 16, 50, 108, 196, 320, 486, 700, 968, 1296, 1690, 2156, 2700, 3328, 4046, 4860, 5776, 6800, 7938, 9196, 10580, 12096, 13750, 15548, 17496, 19600, 21866, 24300, 26908, 29696, 32670
+};
+TYPE res_test0110[32] = {
+ 4, 0, -16, -50, -108, -196, -320, -486, -700, -968, -1296, -1690, -2156, -2700, -3328, -4046, -4860, -5776, -6800, -7938, -9196, -10580, -12096, -13750, -15548, -17496, -19600, -21866, -24300, -26908, -29696, -32670
+};
+TYPE res_test0111[32] = {
+ -2, -8, -26, -62, -122, -212, -338, -506, -722, -992, -1322, -1718, -2186, -2732, -3362, -4082, -4898, -5816, -6842, -7982, -9242, -10628, -12146, -13802, -15602, -17552, -19658, -21926, -24362, -26972, -29762, -32738
+};
+TYPE res_test1000[32] = {
+ 4, 0, -16, -50, -108, -196, -320, -486, -700, -968, -1296, -1690, -2156, -2700, -3328, -4046, -4860, -5776, -6800, -7938, -9196, -10580, -12096, -13750, -15548, -17496, -19600, -21866, -24300, -26908, -29696, -32670
+};
+TYPE res_test1001[32] = {
+ -2, -8, -26, -62, -122, -212, -338, -506, -722, -992, -1322, -1718, -2186, -2732, -3362, -4082, -4898, -5816, -6842, -7982, -9242, -10628, -12146, -13802, -15602, -17552, -19658, -21926, -24362, -26972, -29762, -32738
+};
+TYPE res_test1010[32] = {
+ 2, 8, 26, 62, 122, 212, 338, 506, 722, 992, 1322, 1718, 2186, 2732, 3362, 4082, 4898, 5816, 6842, 7982, 9242, 10628, 12146, 13802, 15602, 17552, 19658, 21926, 24362, 26972, 29762, 32738
+};
+TYPE res_test1011[32] = {
+ -4, 0, 16, 50, 108, 196, 320, 486, 700, 968, 1296, 1690, 2156, 2700, 3328, 4046, 4860, 5776, 6800, 7938, 9196, 10580, 12096, 13750, 15548, 17496, 19600, 21866, 24300, 26908, 29696, 32670
+};
+TYPE res_test1100[32] = {
+ -2, -16, -46, -98, -178, -292, -446, -646, -898, -1208, -1582, -2026, -2546, -3148, -3838, -4622, -5506, -6496, -7598, -8818, -10162, -11636, -13246, -14998, -16898, -18952, -21166, -23546, -26098, -28828, -31742, -34846
+};
+TYPE res_test1101[32] = {
+ -8, -24, -56, -110, -192, -308, -464, -666, -920, -1232, -1608, -2054, -2576, -3180, -3872, -4658, -5544, -6536, -7640, -8862, -10208, -11684, -13296, -15050, -16952, -19008, -21224, -23606, -26160, -28892, -31808, -34914
+};
+TYPE res_test1110[32] = {
+ 8, 24, 56, 110, 192, 308, 464, 666, 920, 1232, 1608, 2054, 2576, 3180, 3872, 4658, 5544, 6536, 7640, 8862, 10208, 11684, 13296, 15050, 16952, 19008, 21224, 23606, 26160, 28892, 31808, 34914
+};
+TYPE res_test1111[32] = {
+ 2, 16, 46, 98, 178, 292, 446, 646, 898, 1208, 1582, 2026, 2546, 3148, 3838, 4622, 5506, 6496, 7598, 8818, 10162, 11636, 13246, 14998, 16898, 18952, 21166, 23546, 26098, 28828, 31742, 34846
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_results_3.h b/gcc/testsuite/gcc.target/i386/fma_run_double_results_3.h
new file mode 100644
index 00000000000..44cf82735d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_results_3.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_double_results_3
+#define fma_run_double_results_3
+
+TYPE res_test0000[32] = {
+ 11, 32, 71, 134, 227, 356, 527, 746, 1019, 1352, 1751, 2222, 2771, 3404, 4127, 4946, 5867, 6896, 8039, 9302, 10691, 12212, 13871, 15674, 17627, 19736, 22007, 24446, 27059, 29852, 32831, 36002
+};
+TYPE res_test0001[32] = {
+ 9, 28, 65, 126, 217, 344, 513, 730, 1001, 1332, 1729, 2198, 2745, 3376, 4097, 4914, 5833, 6860, 8001, 9262, 10649, 12168, 13825, 15626, 17577, 19684, 21953, 24390, 27001, 29792, 32769, 35938
+};
+TYPE res_test0010[32] = {
+ -9, -28, -65, -126, -217, -344, -513, -730, -1001, -1332, -1729, -2198, -2745, -3376, -4097, -4914, -5833, -6860, -8001, -9262, -10649, -12168, -13825, -15626, -17577, -19684, -21953, -24390, -27001, -29792, -32769, -35938
+};
+TYPE res_test0011[32] = {
+ -11, -32, -71, -134, -227, -356, -527, -746, -1019, -1352, -1751, -2222, -2771, -3404, -4127, -4946, -5867, -6896, -8039, -9302, -10691, -12212, -13871, -15674, -17627, -19736, -22007, -24446, -27059, -29852, -32831, -36002
+};
+TYPE res_test0100[32] = {
+ -1, 8, 31, 74, 143, 244, 383, 566, 799, 1088, 1439, 1858, 2351, 2924, 3583, 4334, 5183, 6136, 7199, 8378, 9679, 11108, 12671, 14374, 16223, 18224, 20383, 22706, 25199, 27868, 30719, 33758
+};
+TYPE res_test0101[32] = {
+ -3, 4, 25, 66, 133, 232, 369, 550, 781, 1068, 1417, 1834, 2325, 2896, 3553, 4302, 5149, 6100, 7161, 8338, 9637, 11064, 12625, 14326, 16173, 18172, 20329, 22650, 25141, 27808, 30657, 33694
+};
+TYPE res_test0110[32] = {
+ 3, -4, -25, -66, -133, -232, -369, -550, -781, -1068, -1417, -1834, -2325, -2896, -3553, -4302, -5149, -6100, -7161, -8338, -9637, -11064, -12625, -14326, -16173, -18172, -20329, -22650, -25141, -27808, -30657, -33694
+};
+TYPE res_test0111[32] = {
+ 1, -8, -31, -74, -143, -244, -383, -566, -799, -1088, -1439, -1858, -2351, -2924, -3583, -4334, -5183, -6136, -7199, -8378, -9679, -11108, -12671, -14374, -16223, -18224, -20383, -22706, -25199, -27868, -30719, -33758
+};
+TYPE res_test1000[32] = {
+ 3, -4, -25, -66, -133, -232, -369, -550, -781, -1068, -1417, -1834, -2325, -2896, -3553, -4302, -5149, -6100, -7161, -8338, -9637, -11064, -12625, -14326, -16173, -18172, -20329, -22650, -25141, -27808, -30657, -33694
+};
+TYPE res_test1001[32] = {
+ 1, -8, -31, -74, -143, -244, -383, -566, -799, -1088, -1439, -1858, -2351, -2924, -3583, -4334, -5183, -6136, -7199, -8378, -9679, -11108, -12671, -14374, -16223, -18224, -20383, -22706, -25199, -27868, -30719, -33758
+};
+TYPE res_test1010[32] = {
+ -1, 8, 31, 74, 143, 244, 383, 566, 799, 1088, 1439, 1858, 2351, 2924, 3583, 4334, 5183, 6136, 7199, 8378, 9679, 11108, 12671, 14374, 16223, 18224, 20383, 22706, 25199, 27868, 30719, 33758
+};
+TYPE res_test1011[32] = {
+ -3, 4, 25, 66, 133, 232, 369, 550, 781, 1068, 1417, 1834, 2325, 2896, 3553, 4302, 5149, 6100, 7161, 8338, 9637, 11064, 12625, 14326, 16173, 18172, 20329, 22650, 25141, 27808, 30657, 33694
+};
+TYPE res_test1100[32] = {
+ -9, -28, -65, -126, -217, -344, -513, -730, -1001, -1332, -1729, -2198, -2745, -3376, -4097, -4914, -5833, -6860, -8001, -9262, -10649, -12168, -13825, -15626, -17577, -19684, -21953, -24390, -27001, -29792, -32769, -35938
+};
+TYPE res_test1101[32] = {
+ -11, -32, -71, -134, -227, -356, -527, -746, -1019, -1352, -1751, -2222, -2771, -3404, -4127, -4946, -5867, -6896, -8039, -9302, -10691, -12212, -13871, -15674, -17627, -19736, -22007, -24446, -27059, -29852, -32831, -36002
+};
+TYPE res_test1110[32] = {
+ 11, 32, 71, 134, 227, 356, 527, 746, 1019, 1352, 1751, 2222, 2771, 3404, 4127, 4946, 5867, 6896, 8039, 9302, 10691, 12212, 13871, 15674, 17627, 19736, 22007, 24446, 27059, 29852, 32831, 36002
+};
+TYPE res_test1111[32] = {
+ 9, 28, 65, 126, 217, 344, 513, 730, 1001, 1332, 1729, 2198, 2745, 3376, 4097, 4914, 5833, 6860, 8001, 9262, 10649, 12168, 13825, 15626, 17577, 19684, 21953, 24390, 27001, 29792, 32769, 35938
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_results_4.h b/gcc/testsuite/gcc.target/i386/fma_run_double_results_4.h
new file mode 100644
index 00000000000..0b7f85775cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_results_4.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_double_results_4
+#define fma_run_double_results_4
+
+TYPE res_test0000[32] = {
+ 13, 34, 73, 136, 229, 358, 529, 748, 1021, 1354, 1753, 2224, 2773, 3406, 4129, 4948, 5869, 6898, 8041, 9304, 10693, 12214, 13873, 15676, 17629, 19738, 22009, 24448, 27061, 29854, 32833, 36004
+};
+TYPE res_test0001[32] = {
+ 7, 26, 63, 124, 215, 342, 511, 728, 999, 1330, 1727, 2196, 2743, 3374, 4095, 4912, 5831, 6858, 7999, 9260, 10647, 12166, 13823, 15624, 17575, 19682, 21951, 24388, 26999, 29790, 32767, 35936
+};
+TYPE res_test0010[32] = {
+ -7, -26, -63, -124, -215, -342, -511, -728, -999, -1330, -1727, -2196, -2743, -3374, -4095, -4912, -5831, -6858, -7999, -9260, -10647, -12166, -13823, -15624, -17575, -19682, -21951, -24388, -26999, -29790, -32767, -35936
+};
+TYPE res_test0011[32] = {
+ -13, -34, -73, -136, -229, -358, -529, -748, -1021, -1354, -1753, -2224, -2773, -3406, -4129, -4948, -5869, -6898, -8041, -9304, -10693, -12214, -13873, -15676, -17629, -19738, -22009, -24448, -27061, -29854, -32833, -36004
+};
+TYPE res_test0100[32] = {
+ 1, 10, 33, 76, 145, 246, 385, 568, 801, 1090, 1441, 1860, 2353, 2926, 3585, 4336, 5185, 6138, 7201, 8380, 9681, 11110, 12673, 14376, 16225, 18226, 20385, 22708, 25201, 27870, 30721, 33760
+};
+TYPE res_test0101[32] = {
+ -5, 2, 23, 64, 131, 230, 367, 548, 779, 1066, 1415, 1832, 2323, 2894, 3551, 4300, 5147, 6098, 7159, 8336, 9635, 11062, 12623, 14324, 16171, 18170, 20327, 22648, 25139, 27806, 30655, 33692
+};
+TYPE res_test0110[32] = {
+ 5, -2, -23, -64, -131, -230, -367, -548, -779, -1066, -1415, -1832, -2323, -2894, -3551, -4300, -5147, -6098, -7159, -8336, -9635, -11062, -12623, -14324, -16171, -18170, -20327, -22648, -25139, -27806, -30655, -33692
+};
+TYPE res_test0111[32] = {
+ -1, -10, -33, -76, -145, -246, -385, -568, -801, -1090, -1441, -1860, -2353, -2926, -3585, -4336, -5185, -6138, -7201, -8380, -9681, -11110, -12673, -14376, -16225, -18226, -20385, -22708, -25201, -27870, -30721, -33760
+};
+TYPE res_test1000[32] = {
+ 5, -2, -23, -64, -131, -230, -367, -548, -779, -1066, -1415, -1832, -2323, -2894, -3551, -4300, -5147, -6098, -7159, -8336, -9635, -11062, -12623, -14324, -16171, -18170, -20327, -22648, -25139, -27806, -30655, -33692
+};
+TYPE res_test1001[32] = {
+ -1, -10, -33, -76, -145, -246, -385, -568, -801, -1090, -1441, -1860, -2353, -2926, -3585, -4336, -5185, -6138, -7201, -8380, -9681, -11110, -12673, -14376, -16225, -18226, -20385, -22708, -25201, -27870, -30721, -33760
+};
+TYPE res_test1010[32] = {
+ 1, 10, 33, 76, 145, 246, 385, 568, 801, 1090, 1441, 1860, 2353, 2926, 3585, 4336, 5185, 6138, 7201, 8380, 9681, 11110, 12673, 14376, 16225, 18226, 20385, 22708, 25201, 27870, 30721, 33760
+};
+TYPE res_test1011[32] = {
+ -5, 2, 23, 64, 131, 230, 367, 548, 779, 1066, 1415, 1832, 2323, 2894, 3551, 4300, 5147, 6098, 7159, 8336, 9635, 11062, 12623, 14324, 16171, 18170, 20327, 22648, 25139, 27806, 30655, 33692
+};
+TYPE res_test1100[32] = {
+ -7, -26, -63, -124, -215, -342, -511, -728, -999, -1330, -1727, -2196, -2743, -3374, -4095, -4912, -5831, -6858, -7999, -9260, -10647, -12166, -13823, -15624, -17575, -19682, -21951, -24388, -26999, -29790, -32767, -35936
+};
+TYPE res_test1101[32] = {
+ -13, -34, -73, -136, -229, -358, -529, -748, -1021, -1354, -1753, -2224, -2773, -3406, -4129, -4948, -5869, -6898, -8041, -9304, -10693, -12214, -13873, -15676, -17629, -19738, -22009, -24448, -27061, -29854, -32833, -36004
+};
+TYPE res_test1110[32] = {
+ 13, 34, 73, 136, 229, 358, 529, 748, 1021, 1354, 1753, 2224, 2773, 3406, 4129, 4948, 5869, 6898, 8041, 9304, 10693, 12214, 13873, 15676, 17629, 19738, 22009, 24448, 27061, 29854, 32833, 36004
+};
+TYPE res_test1111[32] = {
+ 7, 26, 63, 124, 215, 342, 511, 728, 999, 1330, 1727, 2196, 2743, 3374, 4095, 4912, 5831, 6858, 7999, 9260, 10647, 12166, 13823, 15624, 17575, 19682, 21951, 24388, 26999, 29790, 32767, 35936
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_results_5.h b/gcc/testsuite/gcc.target/i386/fma_run_double_results_5.h
new file mode 100644
index 00000000000..0f96cad0114
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_results_5.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_double_results_5
+#define fma_run_double_results_5
+
+TYPE res_test0000[32] = {
+ 16, 42, 88, 160, 264, 406, 592, 828, 1120, 1474, 1896, 2392, 2968, 3630, 4384, 5236, 6192, 7258, 8440, 9744, 11176, 12742, 14448, 16300, 18304, 20466, 22792, 25288, 27960, 30814, 33856, 37092
+};
+TYPE res_test0001[32] = {
+ 14, 38, 82, 152, 254, 394, 578, 812, 1102, 1454, 1874, 2368, 2942, 3602, 4354, 5204, 6158, 7222, 8402, 9704, 11134, 12698, 14402, 16252, 18254, 20414, 22738, 25232, 27902, 30754, 33794, 37028
+};
+TYPE res_test0010[32] = {
+ -14, -38, -82, -152, -254, -394, -578, -812, -1102, -1454, -1874, -2368, -2942, -3602, -4354, -5204, -6158, -7222, -8402, -9704, -11134, -12698, -14402, -16252, -18254, -20414, -22738, -25232, -27902, -30754, -33794, -37028
+};
+TYPE res_test0011[32] = {
+ -16, -42, -88, -160, -264, -406, -592, -828, -1120, -1474, -1896, -2392, -2968, -3630, -4384, -5236, -6192, -7258, -8440, -9744, -11176, -12742, -14448, -16300, -18304, -20466, -22792, -25288, -27960, -30814, -33856, -37092
+};
+TYPE res_test0100[32] = {
+ -2, 10, 38, 88, 166, 278, 430, 628, 878, 1186, 1558, 2000, 2518, 3118, 3806, 4588, 5470, 6458, 7558, 8776, 10118, 11590, 13198, 14948, 16846, 18898, 21110, 23488, 26038, 28766, 31678, 34780
+};
+TYPE res_test0101[32] = {
+ -4, 6, 32, 80, 156, 266, 416, 612, 860, 1166, 1536, 1976, 2492, 3090, 3776, 4556, 5436, 6422, 7520, 8736, 10076, 11546, 13152, 14900, 16796, 18846, 21056, 23432, 25980, 28706, 31616, 34716
+};
+TYPE res_test0110[32] = {
+ 4, -6, -32, -80, -156, -266, -416, -612, -860, -1166, -1536, -1976, -2492, -3090, -3776, -4556, -5436, -6422, -7520, -8736, -10076, -11546, -13152, -14900, -16796, -18846, -21056, -23432, -25980, -28706, -31616, -34716
+};
+TYPE res_test0111[32] = {
+ 2, -10, -38, -88, -166, -278, -430, -628, -878, -1186, -1558, -2000, -2518, -3118, -3806, -4588, -5470, -6458, -7558, -8776, -10118, -11590, -13198, -14948, -16846, -18898, -21110, -23488, -26038, -28766, -31678, -34780
+};
+TYPE res_test1000[32] = {
+ 4, -6, -32, -80, -156, -266, -416, -612, -860, -1166, -1536, -1976, -2492, -3090, -3776, -4556, -5436, -6422, -7520, -8736, -10076, -11546, -13152, -14900, -16796, -18846, -21056, -23432, -25980, -28706, -31616, -34716
+};
+TYPE res_test1001[32] = {
+ 2, -10, -38, -88, -166, -278, -430, -628, -878, -1186, -1558, -2000, -2518, -3118, -3806, -4588, -5470, -6458, -7558, -8776, -10118, -11590, -13198, -14948, -16846, -18898, -21110, -23488, -26038, -28766, -31678, -34780
+};
+TYPE res_test1010[32] = {
+ -2, 10, 38, 88, 166, 278, 430, 628, 878, 1186, 1558, 2000, 2518, 3118, 3806, 4588, 5470, 6458, 7558, 8776, 10118, 11590, 13198, 14948, 16846, 18898, 21110, 23488, 26038, 28766, 31678, 34780
+};
+TYPE res_test1011[32] = {
+ -4, 6, 32, 80, 156, 266, 416, 612, 860, 1166, 1536, 1976, 2492, 3090, 3776, 4556, 5436, 6422, 7520, 8736, 10076, 11546, 13152, 14900, 16796, 18846, 21056, 23432, 25980, 28706, 31616, 34716
+};
+TYPE res_test1100[32] = {
+ -14, -38, -82, -152, -254, -394, -578, -812, -1102, -1454, -1874, -2368, -2942, -3602, -4354, -5204, -6158, -7222, -8402, -9704, -11134, -12698, -14402, -16252, -18254, -20414, -22738, -25232, -27902, -30754, -33794, -37028
+};
+TYPE res_test1101[32] = {
+ -16, -42, -88, -160, -264, -406, -592, -828, -1120, -1474, -1896, -2392, -2968, -3630, -4384, -5236, -6192, -7258, -8440, -9744, -11176, -12742, -14448, -16300, -18304, -20466, -22792, -25288, -27960, -30814, -33856, -37092
+};
+TYPE res_test1110[32] = {
+ 16, 42, 88, 160, 264, 406, 592, 828, 1120, 1474, 1896, 2392, 2968, 3630, 4384, 5236, 6192, 7258, 8440, 9744, 11176, 12742, 14448, 16300, 18304, 20466, 22792, 25288, 27960, 30814, 33856, 37092
+};
+TYPE res_test1111[32] = {
+ 14, 38, 82, 152, 254, 394, 578, 812, 1102, 1454, 1874, 2368, 2942, 3602, 4354, 5204, 6158, 7222, 8402, 9704, 11134, 12698, 14402, 16252, 18254, 20414, 22738, 25232, 27902, 30754, 33794, 37028
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_results_6.h b/gcc/testsuite/gcc.target/i386/fma_run_double_results_6.h
new file mode 100644
index 00000000000..29ae9256c0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_results_6.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_double_results_6
+#define fma_run_double_results_6
+
+TYPE res_test0000[32] = {
+ 17, 43, 89, 161, 265, 407, 593, 829, 1121, 1475, 1897, 2393, 2969, 3631, 4385, 5237, 6193, 7259, 8441, 9745, 11177, 12743, 14449, 16301, 18305, 20467, 22793, 25289, 27961, 30815, 33857, 37093
+};
+TYPE res_test0001[32] = {
+ 13, 37, 81, 151, 253, 393, 577, 811, 1101, 1453, 1873, 2367, 2941, 3601, 4353, 5203, 6157, 7221, 8401, 9703, 11133, 12697, 14401, 16251, 18253, 20413, 22737, 25231, 27901, 30753, 33793, 37027
+};
+TYPE res_test0010[32] = {
+ -13, -37, -81, -151, -253, -393, -577, -811, -1101, -1453, -1873, -2367, -2941, -3601, -4353, -5203, -6157, -7221, -8401, -9703, -11133, -12697, -14401, -16251, -18253, -20413, -22737, -25231, -27901, -30753, -33793, -37027
+};
+TYPE res_test0011[32] = {
+ -17, -43, -89, -161, -265, -407, -593, -829, -1121, -1475, -1897, -2393, -2969, -3631, -4385, -5237, -6193, -7259, -8441, -9745, -11177, -12743, -14449, -16301, -18305, -20467, -22793, -25289, -27961, -30815, -33857, -37093
+};
+TYPE res_test0100[32] = {
+ -1, 11, 39, 89, 167, 279, 431, 629, 879, 1187, 1559, 2001, 2519, 3119, 3807, 4589, 5471, 6459, 7559, 8777, 10119, 11591, 13199, 14949, 16847, 18899, 21111, 23489, 26039, 28767, 31679, 34781
+};
+TYPE res_test0101[32] = {
+ -5, 5, 31, 79, 155, 265, 415, 611, 859, 1165, 1535, 1975, 2491, 3089, 3775, 4555, 5435, 6421, 7519, 8735, 10075, 11545, 13151, 14899, 16795, 18845, 21055, 23431, 25979, 28705, 31615, 34715
+};
+TYPE res_test0110[32] = {
+ 5, -5, -31, -79, -155, -265, -415, -611, -859, -1165, -1535, -1975, -2491, -3089, -3775, -4555, -5435, -6421, -7519, -8735, -10075, -11545, -13151, -14899, -16795, -18845, -21055, -23431, -25979, -28705, -31615, -34715
+};
+TYPE res_test0111[32] = {
+ 1, -11, -39, -89, -167, -279, -431, -629, -879, -1187, -1559, -2001, -2519, -3119, -3807, -4589, -5471, -6459, -7559, -8777, -10119, -11591, -13199, -14949, -16847, -18899, -21111, -23489, -26039, -28767, -31679, -34781
+};
+TYPE res_test1000[32] = {
+ 5, -5, -31, -79, -155, -265, -415, -611, -859, -1165, -1535, -1975, -2491, -3089, -3775, -4555, -5435, -6421, -7519, -8735, -10075, -11545, -13151, -14899, -16795, -18845, -21055, -23431, -25979, -28705, -31615, -34715
+};
+TYPE res_test1001[32] = {
+ 1, -11, -39, -89, -167, -279, -431, -629, -879, -1187, -1559, -2001, -2519, -3119, -3807, -4589, -5471, -6459, -7559, -8777, -10119, -11591, -13199, -14949, -16847, -18899, -21111, -23489, -26039, -28767, -31679, -34781
+};
+TYPE res_test1010[32] = {
+ -1, 11, 39, 89, 167, 279, 431, 629, 879, 1187, 1559, 2001, 2519, 3119, 3807, 4589, 5471, 6459, 7559, 8777, 10119, 11591, 13199, 14949, 16847, 18899, 21111, 23489, 26039, 28767, 31679, 34781
+};
+TYPE res_test1011[32] = {
+ -5, 5, 31, 79, 155, 265, 415, 611, 859, 1165, 1535, 1975, 2491, 3089, 3775, 4555, 5435, 6421, 7519, 8735, 10075, 11545, 13151, 14899, 16795, 18845, 21055, 23431, 25979, 28705, 31615, 34715
+};
+TYPE res_test1100[32] = {
+ -13, -37, -81, -151, -253, -393, -577, -811, -1101, -1453, -1873, -2367, -2941, -3601, -4353, -5203, -6157, -7221, -8401, -9703, -11133, -12697, -14401, -16251, -18253, -20413, -22737, -25231, -27901, -30753, -33793, -37027
+};
+TYPE res_test1101[32] = {
+ -17, -43, -89, -161, -265, -407, -593, -829, -1121, -1475, -1897, -2393, -2969, -3631, -4385, -5237, -6193, -7259, -8441, -9745, -11177, -12743, -14449, -16301, -18305, -20467, -22793, -25289, -27961, -30815, -33857, -37093
+};
+TYPE res_test1110[32] = {
+ 17, 43, 89, 161, 265, 407, 593, 829, 1121, 1475, 1897, 2393, 2969, 3631, 4385, 5237, 6193, 7259, 8441, 9745, 11177, 12743, 14449, 16301, 18305, 20467, 22793, 25289, 27961, 30815, 33857, 37093
+};
+TYPE res_test1111[32] = {
+ 13, 37, 81, 151, 253, 393, 577, 811, 1101, 1453, 1873, 2367, 2941, 3601, 4353, 5203, 6157, 7221, 8401, 9703, 11133, 12697, 14401, 16251, 18253, 20413, 22737, 25231, 27901, 30753, 33793, 37027
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_1.c b/gcc/testsuite/gcc.target/i386/fma_run_float_1.c
new file mode 100644
index 00000000000..eccf60a88cd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_1.h"
+
+#include "fma_run_float_results_1.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_2.c b/gcc/testsuite/gcc.target/i386/fma_run_float_2.c
new file mode 100644
index 00000000000..18177520ac9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_2.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_2.h"
+
+#include "fma_run_float_results_2.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_3.c b/gcc/testsuite/gcc.target/i386/fma_run_float_3.c
new file mode 100644
index 00000000000..b206a0775d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_3.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_3.h"
+
+#include "fma_run_float_results_3.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_4.c b/gcc/testsuite/gcc.target/i386/fma_run_float_4.c
new file mode 100644
index 00000000000..31c5a4dbbf6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_4.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_4.h"
+
+#include "fma_run_float_results_4.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_5.c b/gcc/testsuite/gcc.target/i386/fma_run_float_5.c
new file mode 100644
index 00000000000..615886cedbd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_5.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_5.h"
+
+#include "fma_run_float_results_5.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_6.c b/gcc/testsuite/gcc.target/i386/fma_run_float_6.c
new file mode 100644
index 00000000000..ca6cf5b1c1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_6.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "fma_6.h"
+
+#include "fma_run_float_results_6.h"
+
+#include "fma-check.h"
+#include "fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_results_1.h b/gcc/testsuite/gcc.target/i386/fma_run_float_results_1.h
new file mode 100644
index 00000000000..65f52f2c75d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_results_1.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_float_results_1
+#define fma_run_float_results_1
+
+TYPE res_test0000[32] = {
+ 7, 23, 55, 109, 191, 307, 463, 665, 919, 1231, 1607, 2053, 2575, 3179, 3871, 4657, 5543, 6535, 7639, 8861, 10207, 11683, 13295, 15049, 16951, 19007, 21223, 23605, 26159, 28891, 31807, 34913
+};
+TYPE res_test0001[32] = {
+ 3, 17, 47, 99, 179, 293, 447, 647, 899, 1209, 1583, 2027, 2547, 3149, 3839, 4623, 5507, 6497, 7599, 8819, 10163, 11637, 13247, 14999, 16899, 18953, 21167, 23547, 26099, 28829, 31743, 34847
+};
+TYPE res_test0010[32] = {
+ -3, -17, -47, -99, -179, -293, -447, -647, -899, -1209, -1583, -2027, -2547, -3149, -3839, -4623, -5507, -6497, -7599, -8819, -10163, -11637, -13247, -14999, -16899, -18953, -21167, -23547, -26099, -28829, -31743, -34847
+};
+TYPE res_test0011[32] = {
+ -7, -23, -55, -109, -191, -307, -463, -665, -919, -1231, -1607, -2053, -2575, -3179, -3871, -4657, -5543, -6535, -7639, -8861, -10207, -11683, -13295, -15049, -16951, -19007, -21223, -23605, -26159, -28891, -31807, -34913
+};
+TYPE res_test0100[32] = {
+ 1, 7, 25, 61, 121, 211, 337, 505, 721, 991, 1321, 1717, 2185, 2731, 3361, 4081, 4897, 5815, 6841, 7981, 9241, 10627, 12145, 13801, 15601, 17551, 19657, 21925, 24361, 26971, 29761, 32737
+};
+TYPE res_test0101[32] = {
+ -3, 1, 17, 51, 109, 197, 321, 487, 701, 969, 1297, 1691, 2157, 2701, 3329, 4047, 4861, 5777, 6801, 7939, 9197, 10581, 12097, 13751, 15549, 17497, 19601, 21867, 24301, 26909, 29697, 32671
+};
+TYPE res_test0110[32] = {
+ 3, -1, -17, -51, -109, -197, -321, -487, -701, -969, -1297, -1691, -2157, -2701, -3329, -4047, -4861, -5777, -6801, -7939, -9197, -10581, -12097, -13751, -15549, -17497, -19601, -21867, -24301, -26909, -29697, -32671
+};
+TYPE res_test0111[32] = {
+ -1, -7, -25, -61, -121, -211, -337, -505, -721, -991, -1321, -1717, -2185, -2731, -3361, -4081, -4897, -5815, -6841, -7981, -9241, -10627, -12145, -13801, -15601, -17551, -19657, -21925, -24361, -26971, -29761, -32737
+};
+TYPE res_test1000[32] = {
+ 3, -1, -17, -51, -109, -197, -321, -487, -701, -969, -1297, -1691, -2157, -2701, -3329, -4047, -4861, -5777, -6801, -7939, -9197, -10581, -12097, -13751, -15549, -17497, -19601, -21867, -24301, -26909, -29697, -32671
+};
+TYPE res_test1001[32] = {
+ -1, -7, -25, -61, -121, -211, -337, -505, -721, -991, -1321, -1717, -2185, -2731, -3361, -4081, -4897, -5815, -6841, -7981, -9241, -10627, -12145, -13801, -15601, -17551, -19657, -21925, -24361, -26971, -29761, -32737
+};
+TYPE res_test1010[32] = {
+ 1, 7, 25, 61, 121, 211, 337, 505, 721, 991, 1321, 1717, 2185, 2731, 3361, 4081, 4897, 5815, 6841, 7981, 9241, 10627, 12145, 13801, 15601, 17551, 19657, 21925, 24361, 26971, 29761, 32737
+};
+TYPE res_test1011[32] = {
+ -3, 1, 17, 51, 109, 197, 321, 487, 701, 969, 1297, 1691, 2157, 2701, 3329, 4047, 4861, 5777, 6801, 7939, 9197, 10581, 12097, 13751, 15549, 17497, 19601, 21867, 24301, 26909, 29697, 32671
+};
+TYPE res_test1100[32] = {
+ -3, -17, -47, -99, -179, -293, -447, -647, -899, -1209, -1583, -2027, -2547, -3149, -3839, -4623, -5507, -6497, -7599, -8819, -10163, -11637, -13247, -14999, -16899, -18953, -21167, -23547, -26099, -28829, -31743, -34847
+};
+TYPE res_test1101[32] = {
+ -7, -23, -55, -109, -191, -307, -463, -665, -919, -1231, -1607, -2053, -2575, -3179, -3871, -4657, -5543, -6535, -7639, -8861, -10207, -11683, -13295, -15049, -16951, -19007, -21223, -23605, -26159, -28891, -31807, -34913
+};
+TYPE res_test1110[32] = {
+ 7, 23, 55, 109, 191, 307, 463, 665, 919, 1231, 1607, 2053, 2575, 3179, 3871, 4657, 5543, 6535, 7639, 8861, 10207, 11683, 13295, 15049, 16951, 19007, 21223, 23605, 26159, 28891, 31807, 34913
+};
+TYPE res_test1111[32] = {
+ 3, 17, 47, 99, 179, 293, 447, 647, 899, 1209, 1583, 2027, 2547, 3149, 3839, 4623, 5507, 6497, 7599, 8819, 10163, 11637, 13247, 14999, 16899, 18953, 21167, 23547, 26099, 28829, 31743, 34847
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_results_2.h b/gcc/testsuite/gcc.target/i386/fma_run_float_results_2.h
new file mode 100644
index 00000000000..d215efd587c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_results_2.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_float_results_2
+#define fma_run_float_results_2
+
+TYPE res_test0000[32] = {
+ 8, 24, 56, 110, 192, 308, 464, 666, 920, 1232, 1608, 2054, 2576, 3180, 3872, 4658, 5544, 6536, 7640, 8862, 10208, 11684, 13296, 15050, 16952, 19008, 21224, 23606, 26160, 28892, 31808, 34914
+};
+TYPE res_test0001[32] = {
+ 2, 16, 46, 98, 178, 292, 446, 646, 898, 1208, 1582, 2026, 2546, 3148, 3838, 4622, 5506, 6496, 7598, 8818, 10162, 11636, 13246, 14998, 16898, 18952, 21166, 23546, 26098, 28828, 31742, 34846
+};
+TYPE res_test0010[32] = {
+ -2, -16, -46, -98, -178, -292, -446, -646, -898, -1208, -1582, -2026, -2546, -3148, -3838, -4622, -5506, -6496, -7598, -8818, -10162, -11636, -13246, -14998, -16898, -18952, -21166, -23546, -26098, -28828, -31742, -34846
+};
+TYPE res_test0011[32] = {
+ -8, -24, -56, -110, -192, -308, -464, -666, -920, -1232, -1608, -2054, -2576, -3180, -3872, -4658, -5544, -6536, -7640, -8862, -10208, -11684, -13296, -15050, -16952, -19008, -21224, -23606, -26160, -28892, -31808, -34914
+};
+TYPE res_test0100[32] = {
+ 2, 8, 26, 62, 122, 212, 338, 506, 722, 992, 1322, 1718, 2186, 2732, 3362, 4082, 4898, 5816, 6842, 7982, 9242, 10628, 12146, 13802, 15602, 17552, 19658, 21926, 24362, 26972, 29762, 32738
+};
+TYPE res_test0101[32] = {
+ -4, 0, 16, 50, 108, 196, 320, 486, 700, 968, 1296, 1690, 2156, 2700, 3328, 4046, 4860, 5776, 6800, 7938, 9196, 10580, 12096, 13750, 15548, 17496, 19600, 21866, 24300, 26908, 29696, 32670
+};
+TYPE res_test0110[32] = {
+ 4, 0, -16, -50, -108, -196, -320, -486, -700, -968, -1296, -1690, -2156, -2700, -3328, -4046, -4860, -5776, -6800, -7938, -9196, -10580, -12096, -13750, -15548, -17496, -19600, -21866, -24300, -26908, -29696, -32670
+};
+TYPE res_test0111[32] = {
+ -2, -8, -26, -62, -122, -212, -338, -506, -722, -992, -1322, -1718, -2186, -2732, -3362, -4082, -4898, -5816, -6842, -7982, -9242, -10628, -12146, -13802, -15602, -17552, -19658, -21926, -24362, -26972, -29762, -32738
+};
+TYPE res_test1000[32] = {
+ 4, 0, -16, -50, -108, -196, -320, -486, -700, -968, -1296, -1690, -2156, -2700, -3328, -4046, -4860, -5776, -6800, -7938, -9196, -10580, -12096, -13750, -15548, -17496, -19600, -21866, -24300, -26908, -29696, -32670
+};
+TYPE res_test1001[32] = {
+ -2, -8, -26, -62, -122, -212, -338, -506, -722, -992, -1322, -1718, -2186, -2732, -3362, -4082, -4898, -5816, -6842, -7982, -9242, -10628, -12146, -13802, -15602, -17552, -19658, -21926, -24362, -26972, -29762, -32738
+};
+TYPE res_test1010[32] = {
+ 2, 8, 26, 62, 122, 212, 338, 506, 722, 992, 1322, 1718, 2186, 2732, 3362, 4082, 4898, 5816, 6842, 7982, 9242, 10628, 12146, 13802, 15602, 17552, 19658, 21926, 24362, 26972, 29762, 32738
+};
+TYPE res_test1011[32] = {
+ -4, 0, 16, 50, 108, 196, 320, 486, 700, 968, 1296, 1690, 2156, 2700, 3328, 4046, 4860, 5776, 6800, 7938, 9196, 10580, 12096, 13750, 15548, 17496, 19600, 21866, 24300, 26908, 29696, 32670
+};
+TYPE res_test1100[32] = {
+ -2, -16, -46, -98, -178, -292, -446, -646, -898, -1208, -1582, -2026, -2546, -3148, -3838, -4622, -5506, -6496, -7598, -8818, -10162, -11636, -13246, -14998, -16898, -18952, -21166, -23546, -26098, -28828, -31742, -34846
+};
+TYPE res_test1101[32] = {
+ -8, -24, -56, -110, -192, -308, -464, -666, -920, -1232, -1608, -2054, -2576, -3180, -3872, -4658, -5544, -6536, -7640, -8862, -10208, -11684, -13296, -15050, -16952, -19008, -21224, -23606, -26160, -28892, -31808, -34914
+};
+TYPE res_test1110[32] = {
+ 8, 24, 56, 110, 192, 308, 464, 666, 920, 1232, 1608, 2054, 2576, 3180, 3872, 4658, 5544, 6536, 7640, 8862, 10208, 11684, 13296, 15050, 16952, 19008, 21224, 23606, 26160, 28892, 31808, 34914
+};
+TYPE res_test1111[32] = {
+ 2, 16, 46, 98, 178, 292, 446, 646, 898, 1208, 1582, 2026, 2546, 3148, 3838, 4622, 5506, 6496, 7598, 8818, 10162, 11636, 13246, 14998, 16898, 18952, 21166, 23546, 26098, 28828, 31742, 34846
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_results_3.h b/gcc/testsuite/gcc.target/i386/fma_run_float_results_3.h
new file mode 100644
index 00000000000..11751f131a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_results_3.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_float_results_3
+#define fma_run_float_results_3
+
+TYPE res_test0000[32] = {
+ 11, 32, 71, 134, 227, 356, 527, 746, 1019, 1352, 1751, 2222, 2771, 3404, 4127, 4946, 5867, 6896, 8039, 9302, 10691, 12212, 13871, 15674, 17627, 19736, 22007, 24446, 27059, 29852, 32831, 36002
+};
+TYPE res_test0001[32] = {
+ 9, 28, 65, 126, 217, 344, 513, 730, 1001, 1332, 1729, 2198, 2745, 3376, 4097, 4914, 5833, 6860, 8001, 9262, 10649, 12168, 13825, 15626, 17577, 19684, 21953, 24390, 27001, 29792, 32769, 35938
+};
+TYPE res_test0010[32] = {
+ -9, -28, -65, -126, -217, -344, -513, -730, -1001, -1332, -1729, -2198, -2745, -3376, -4097, -4914, -5833, -6860, -8001, -9262, -10649, -12168, -13825, -15626, -17577, -19684, -21953, -24390, -27001, -29792, -32769, -35938
+};
+TYPE res_test0011[32] = {
+ -11, -32, -71, -134, -227, -356, -527, -746, -1019, -1352, -1751, -2222, -2771, -3404, -4127, -4946, -5867, -6896, -8039, -9302, -10691, -12212, -13871, -15674, -17627, -19736, -22007, -24446, -27059, -29852, -32831, -36002
+};
+TYPE res_test0100[32] = {
+ -1, 8, 31, 74, 143, 244, 383, 566, 799, 1088, 1439, 1858, 2351, 2924, 3583, 4334, 5183, 6136, 7199, 8378, 9679, 11108, 12671, 14374, 16223, 18224, 20383, 22706, 25199, 27868, 30719, 33758
+};
+TYPE res_test0101[32] = {
+ -3, 4, 25, 66, 133, 232, 369, 550, 781, 1068, 1417, 1834, 2325, 2896, 3553, 4302, 5149, 6100, 7161, 8338, 9637, 11064, 12625, 14326, 16173, 18172, 20329, 22650, 25141, 27808, 30657, 33694
+};
+TYPE res_test0110[32] = {
+ 3, -4, -25, -66, -133, -232, -369, -550, -781, -1068, -1417, -1834, -2325, -2896, -3553, -4302, -5149, -6100, -7161, -8338, -9637, -11064, -12625, -14326, -16173, -18172, -20329, -22650, -25141, -27808, -30657, -33694
+};
+TYPE res_test0111[32] = {
+ 1, -8, -31, -74, -143, -244, -383, -566, -799, -1088, -1439, -1858, -2351, -2924, -3583, -4334, -5183, -6136, -7199, -8378, -9679, -11108, -12671, -14374, -16223, -18224, -20383, -22706, -25199, -27868, -30719, -33758
+};
+TYPE res_test1000[32] = {
+ 3, -4, -25, -66, -133, -232, -369, -550, -781, -1068, -1417, -1834, -2325, -2896, -3553, -4302, -5149, -6100, -7161, -8338, -9637, -11064, -12625, -14326, -16173, -18172, -20329, -22650, -25141, -27808, -30657, -33694
+};
+TYPE res_test1001[32] = {
+ 1, -8, -31, -74, -143, -244, -383, -566, -799, -1088, -1439, -1858, -2351, -2924, -3583, -4334, -5183, -6136, -7199, -8378, -9679, -11108, -12671, -14374, -16223, -18224, -20383, -22706, -25199, -27868, -30719, -33758
+};
+TYPE res_test1010[32] = {
+ -1, 8, 31, 74, 143, 244, 383, 566, 799, 1088, 1439, 1858, 2351, 2924, 3583, 4334, 5183, 6136, 7199, 8378, 9679, 11108, 12671, 14374, 16223, 18224, 20383, 22706, 25199, 27868, 30719, 33758
+};
+TYPE res_test1011[32] = {
+ -3, 4, 25, 66, 133, 232, 369, 550, 781, 1068, 1417, 1834, 2325, 2896, 3553, 4302, 5149, 6100, 7161, 8338, 9637, 11064, 12625, 14326, 16173, 18172, 20329, 22650, 25141, 27808, 30657, 33694
+};
+TYPE res_test1100[32] = {
+ -9, -28, -65, -126, -217, -344, -513, -730, -1001, -1332, -1729, -2198, -2745, -3376, -4097, -4914, -5833, -6860, -8001, -9262, -10649, -12168, -13825, -15626, -17577, -19684, -21953, -24390, -27001, -29792, -32769, -35938
+};
+TYPE res_test1101[32] = {
+ -11, -32, -71, -134, -227, -356, -527, -746, -1019, -1352, -1751, -2222, -2771, -3404, -4127, -4946, -5867, -6896, -8039, -9302, -10691, -12212, -13871, -15674, -17627, -19736, -22007, -24446, -27059, -29852, -32831, -36002
+};
+TYPE res_test1110[32] = {
+ 11, 32, 71, 134, 227, 356, 527, 746, 1019, 1352, 1751, 2222, 2771, 3404, 4127, 4946, 5867, 6896, 8039, 9302, 10691, 12212, 13871, 15674, 17627, 19736, 22007, 24446, 27059, 29852, 32831, 36002
+};
+TYPE res_test1111[32] = {
+ 9, 28, 65, 126, 217, 344, 513, 730, 1001, 1332, 1729, 2198, 2745, 3376, 4097, 4914, 5833, 6860, 8001, 9262, 10649, 12168, 13825, 15626, 17577, 19684, 21953, 24390, 27001, 29792, 32769, 35938
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_results_4.h b/gcc/testsuite/gcc.target/i386/fma_run_float_results_4.h
new file mode 100644
index 00000000000..13906dbdde1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_results_4.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_float_results_4
+#define fma_run_float_results_4
+
+TYPE res_test0000[32] = {
+ 13, 34, 73, 136, 229, 358, 529, 748, 1021, 1354, 1753, 2224, 2773, 3406, 4129, 4948, 5869, 6898, 8041, 9304, 10693, 12214, 13873, 15676, 17629, 19738, 22009, 24448, 27061, 29854, 32833, 36004
+};
+TYPE res_test0001[32] = {
+ 7, 26, 63, 124, 215, 342, 511, 728, 999, 1330, 1727, 2196, 2743, 3374, 4095, 4912, 5831, 6858, 7999, 9260, 10647, 12166, 13823, 15624, 17575, 19682, 21951, 24388, 26999, 29790, 32767, 35936
+};
+TYPE res_test0010[32] = {
+ -7, -26, -63, -124, -215, -342, -511, -728, -999, -1330, -1727, -2196, -2743, -3374, -4095, -4912, -5831, -6858, -7999, -9260, -10647, -12166, -13823, -15624, -17575, -19682, -21951, -24388, -26999, -29790, -32767, -35936
+};
+TYPE res_test0011[32] = {
+ -13, -34, -73, -136, -229, -358, -529, -748, -1021, -1354, -1753, -2224, -2773, -3406, -4129, -4948, -5869, -6898, -8041, -9304, -10693, -12214, -13873, -15676, -17629, -19738, -22009, -24448, -27061, -29854, -32833, -36004
+};
+TYPE res_test0100[32] = {
+ 1, 10, 33, 76, 145, 246, 385, 568, 801, 1090, 1441, 1860, 2353, 2926, 3585, 4336, 5185, 6138, 7201, 8380, 9681, 11110, 12673, 14376, 16225, 18226, 20385, 22708, 25201, 27870, 30721, 33760
+};
+TYPE res_test0101[32] = {
+ -5, 2, 23, 64, 131, 230, 367, 548, 779, 1066, 1415, 1832, 2323, 2894, 3551, 4300, 5147, 6098, 7159, 8336, 9635, 11062, 12623, 14324, 16171, 18170, 20327, 22648, 25139, 27806, 30655, 33692
+};
+TYPE res_test0110[32] = {
+ 5, -2, -23, -64, -131, -230, -367, -548, -779, -1066, -1415, -1832, -2323, -2894, -3551, -4300, -5147, -6098, -7159, -8336, -9635, -11062, -12623, -14324, -16171, -18170, -20327, -22648, -25139, -27806, -30655, -33692
+};
+TYPE res_test0111[32] = {
+ -1, -10, -33, -76, -145, -246, -385, -568, -801, -1090, -1441, -1860, -2353, -2926, -3585, -4336, -5185, -6138, -7201, -8380, -9681, -11110, -12673, -14376, -16225, -18226, -20385, -22708, -25201, -27870, -30721, -33760
+};
+TYPE res_test1000[32] = {
+ 5, -2, -23, -64, -131, -230, -367, -548, -779, -1066, -1415, -1832, -2323, -2894, -3551, -4300, -5147, -6098, -7159, -8336, -9635, -11062, -12623, -14324, -16171, -18170, -20327, -22648, -25139, -27806, -30655, -33692
+};
+TYPE res_test1001[32] = {
+ -1, -10, -33, -76, -145, -246, -385, -568, -801, -1090, -1441, -1860, -2353, -2926, -3585, -4336, -5185, -6138, -7201, -8380, -9681, -11110, -12673, -14376, -16225, -18226, -20385, -22708, -25201, -27870, -30721, -33760
+};
+TYPE res_test1010[32] = {
+ 1, 10, 33, 76, 145, 246, 385, 568, 801, 1090, 1441, 1860, 2353, 2926, 3585, 4336, 5185, 6138, 7201, 8380, 9681, 11110, 12673, 14376, 16225, 18226, 20385, 22708, 25201, 27870, 30721, 33760
+};
+TYPE res_test1011[32] = {
+ -5, 2, 23, 64, 131, 230, 367, 548, 779, 1066, 1415, 1832, 2323, 2894, 3551, 4300, 5147, 6098, 7159, 8336, 9635, 11062, 12623, 14324, 16171, 18170, 20327, 22648, 25139, 27806, 30655, 33692
+};
+TYPE res_test1100[32] = {
+ -7, -26, -63, -124, -215, -342, -511, -728, -999, -1330, -1727, -2196, -2743, -3374, -4095, -4912, -5831, -6858, -7999, -9260, -10647, -12166, -13823, -15624, -17575, -19682, -21951, -24388, -26999, -29790, -32767, -35936
+};
+TYPE res_test1101[32] = {
+ -13, -34, -73, -136, -229, -358, -529, -748, -1021, -1354, -1753, -2224, -2773, -3406, -4129, -4948, -5869, -6898, -8041, -9304, -10693, -12214, -13873, -15676, -17629, -19738, -22009, -24448, -27061, -29854, -32833, -36004
+};
+TYPE res_test1110[32] = {
+ 13, 34, 73, 136, 229, 358, 529, 748, 1021, 1354, 1753, 2224, 2773, 3406, 4129, 4948, 5869, 6898, 8041, 9304, 10693, 12214, 13873, 15676, 17629, 19738, 22009, 24448, 27061, 29854, 32833, 36004
+};
+TYPE res_test1111[32] = {
+ 7, 26, 63, 124, 215, 342, 511, 728, 999, 1330, 1727, 2196, 2743, 3374, 4095, 4912, 5831, 6858, 7999, 9260, 10647, 12166, 13823, 15624, 17575, 19682, 21951, 24388, 26999, 29790, 32767, 35936
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_results_5.h b/gcc/testsuite/gcc.target/i386/fma_run_float_results_5.h
new file mode 100644
index 00000000000..f156bef6f4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_results_5.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_float_results_5
+#define fma_run_float_results_5
+
+TYPE res_test0000[32] = {
+ 16, 42, 88, 160, 264, 406, 592, 828, 1120, 1474, 1896, 2392, 2968, 3630, 4384, 5236, 6192, 7258, 8440, 9744, 11176, 12742, 14448, 16300, 18304, 20466, 22792, 25288, 27960, 30814, 33856, 37092
+};
+TYPE res_test0001[32] = {
+ 14, 38, 82, 152, 254, 394, 578, 812, 1102, 1454, 1874, 2368, 2942, 3602, 4354, 5204, 6158, 7222, 8402, 9704, 11134, 12698, 14402, 16252, 18254, 20414, 22738, 25232, 27902, 30754, 33794, 37028
+};
+TYPE res_test0010[32] = {
+ -14, -38, -82, -152, -254, -394, -578, -812, -1102, -1454, -1874, -2368, -2942, -3602, -4354, -5204, -6158, -7222, -8402, -9704, -11134, -12698, -14402, -16252, -18254, -20414, -22738, -25232, -27902, -30754, -33794, -37028
+};
+TYPE res_test0011[32] = {
+ -16, -42, -88, -160, -264, -406, -592, -828, -1120, -1474, -1896, -2392, -2968, -3630, -4384, -5236, -6192, -7258, -8440, -9744, -11176, -12742, -14448, -16300, -18304, -20466, -22792, -25288, -27960, -30814, -33856, -37092
+};
+TYPE res_test0100[32] = {
+ -2, 10, 38, 88, 166, 278, 430, 628, 878, 1186, 1558, 2000, 2518, 3118, 3806, 4588, 5470, 6458, 7558, 8776, 10118, 11590, 13198, 14948, 16846, 18898, 21110, 23488, 26038, 28766, 31678, 34780
+};
+TYPE res_test0101[32] = {
+ -4, 6, 32, 80, 156, 266, 416, 612, 860, 1166, 1536, 1976, 2492, 3090, 3776, 4556, 5436, 6422, 7520, 8736, 10076, 11546, 13152, 14900, 16796, 18846, 21056, 23432, 25980, 28706, 31616, 34716
+};
+TYPE res_test0110[32] = {
+ 4, -6, -32, -80, -156, -266, -416, -612, -860, -1166, -1536, -1976, -2492, -3090, -3776, -4556, -5436, -6422, -7520, -8736, -10076, -11546, -13152, -14900, -16796, -18846, -21056, -23432, -25980, -28706, -31616, -34716
+};
+TYPE res_test0111[32] = {
+ 2, -10, -38, -88, -166, -278, -430, -628, -878, -1186, -1558, -2000, -2518, -3118, -3806, -4588, -5470, -6458, -7558, -8776, -10118, -11590, -13198, -14948, -16846, -18898, -21110, -23488, -26038, -28766, -31678, -34780
+};
+TYPE res_test1000[32] = {
+ 4, -6, -32, -80, -156, -266, -416, -612, -860, -1166, -1536, -1976, -2492, -3090, -3776, -4556, -5436, -6422, -7520, -8736, -10076, -11546, -13152, -14900, -16796, -18846, -21056, -23432, -25980, -28706, -31616, -34716
+};
+TYPE res_test1001[32] = {
+ 2, -10, -38, -88, -166, -278, -430, -628, -878, -1186, -1558, -2000, -2518, -3118, -3806, -4588, -5470, -6458, -7558, -8776, -10118, -11590, -13198, -14948, -16846, -18898, -21110, -23488, -26038, -28766, -31678, -34780
+};
+TYPE res_test1010[32] = {
+ -2, 10, 38, 88, 166, 278, 430, 628, 878, 1186, 1558, 2000, 2518, 3118, 3806, 4588, 5470, 6458, 7558, 8776, 10118, 11590, 13198, 14948, 16846, 18898, 21110, 23488, 26038, 28766, 31678, 34780
+};
+TYPE res_test1011[32] = {
+ -4, 6, 32, 80, 156, 266, 416, 612, 860, 1166, 1536, 1976, 2492, 3090, 3776, 4556, 5436, 6422, 7520, 8736, 10076, 11546, 13152, 14900, 16796, 18846, 21056, 23432, 25980, 28706, 31616, 34716
+};
+TYPE res_test1100[32] = {
+ -14, -38, -82, -152, -254, -394, -578, -812, -1102, -1454, -1874, -2368, -2942, -3602, -4354, -5204, -6158, -7222, -8402, -9704, -11134, -12698, -14402, -16252, -18254, -20414, -22738, -25232, -27902, -30754, -33794, -37028
+};
+TYPE res_test1101[32] = {
+ -16, -42, -88, -160, -264, -406, -592, -828, -1120, -1474, -1896, -2392, -2968, -3630, -4384, -5236, -6192, -7258, -8440, -9744, -11176, -12742, -14448, -16300, -18304, -20466, -22792, -25288, -27960, -30814, -33856, -37092
+};
+TYPE res_test1110[32] = {
+ 16, 42, 88, 160, 264, 406, 592, 828, 1120, 1474, 1896, 2392, 2968, 3630, 4384, 5236, 6192, 7258, 8440, 9744, 11176, 12742, 14448, 16300, 18304, 20466, 22792, 25288, 27960, 30814, 33856, 37092
+};
+TYPE res_test1111[32] = {
+ 14, 38, 82, 152, 254, 394, 578, 812, 1102, 1454, 1874, 2368, 2942, 3602, 4354, 5204, 6158, 7222, 8402, 9704, 11134, 12698, 14402, 16252, 18254, 20414, 22738, 25232, 27902, 30754, 33794, 37028
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_results_6.h b/gcc/testsuite/gcc.target/i386/fma_run_float_results_6.h
new file mode 100644
index 00000000000..d2c2e1f9728
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_results_6.h
@@ -0,0 +1,54 @@
+
+#ifndef fma_run_float_results_6
+#define fma_run_float_results_6
+
+TYPE res_test0000[32] = {
+ 17, 43, 89, 161, 265, 407, 593, 829, 1121, 1475, 1897, 2393, 2969, 3631, 4385, 5237, 6193, 7259, 8441, 9745, 11177, 12743, 14449, 16301, 18305, 20467, 22793, 25289, 27961, 30815, 33857, 37093
+};
+TYPE res_test0001[32] = {
+ 13, 37, 81, 151, 253, 393, 577, 811, 1101, 1453, 1873, 2367, 2941, 3601, 4353, 5203, 6157, 7221, 8401, 9703, 11133, 12697, 14401, 16251, 18253, 20413, 22737, 25231, 27901, 30753, 33793, 37027
+};
+TYPE res_test0010[32] = {
+ -13, -37, -81, -151, -253, -393, -577, -811, -1101, -1453, -1873, -2367, -2941, -3601, -4353, -5203, -6157, -7221, -8401, -9703, -11133, -12697, -14401, -16251, -18253, -20413, -22737, -25231, -27901, -30753, -33793, -37027
+};
+TYPE res_test0011[32] = {
+ -17, -43, -89, -161, -265, -407, -593, -829, -1121, -1475, -1897, -2393, -2969, -3631, -4385, -5237, -6193, -7259, -8441, -9745, -11177, -12743, -14449, -16301, -18305, -20467, -22793, -25289, -27961, -30815, -33857, -37093
+};
+TYPE res_test0100[32] = {
+ -1, 11, 39, 89, 167, 279, 431, 629, 879, 1187, 1559, 2001, 2519, 3119, 3807, 4589, 5471, 6459, 7559, 8777, 10119, 11591, 13199, 14949, 16847, 18899, 21111, 23489, 26039, 28767, 31679, 34781
+};
+TYPE res_test0101[32] = {
+ -5, 5, 31, 79, 155, 265, 415, 611, 859, 1165, 1535, 1975, 2491, 3089, 3775, 4555, 5435, 6421, 7519, 8735, 10075, 11545, 13151, 14899, 16795, 18845, 21055, 23431, 25979, 28705, 31615, 34715
+};
+TYPE res_test0110[32] = {
+ 5, -5, -31, -79, -155, -265, -415, -611, -859, -1165, -1535, -1975, -2491, -3089, -3775, -4555, -5435, -6421, -7519, -8735, -10075, -11545, -13151, -14899, -16795, -18845, -21055, -23431, -25979, -28705, -31615, -34715
+};
+TYPE res_test0111[32] = {
+ 1, -11, -39, -89, -167, -279, -431, -629, -879, -1187, -1559, -2001, -2519, -3119, -3807, -4589, -5471, -6459, -7559, -8777, -10119, -11591, -13199, -14949, -16847, -18899, -21111, -23489, -26039, -28767, -31679, -34781
+};
+TYPE res_test1000[32] = {
+ 5, -5, -31, -79, -155, -265, -415, -611, -859, -1165, -1535, -1975, -2491, -3089, -3775, -4555, -5435, -6421, -7519, -8735, -10075, -11545, -13151, -14899, -16795, -18845, -21055, -23431, -25979, -28705, -31615, -34715
+};
+TYPE res_test1001[32] = {
+ 1, -11, -39, -89, -167, -279, -431, -629, -879, -1187, -1559, -2001, -2519, -3119, -3807, -4589, -5471, -6459, -7559, -8777, -10119, -11591, -13199, -14949, -16847, -18899, -21111, -23489, -26039, -28767, -31679, -34781
+};
+TYPE res_test1010[32] = {
+ -1, 11, 39, 89, 167, 279, 431, 629, 879, 1187, 1559, 2001, 2519, 3119, 3807, 4589, 5471, 6459, 7559, 8777, 10119, 11591, 13199, 14949, 16847, 18899, 21111, 23489, 26039, 28767, 31679, 34781
+};
+TYPE res_test1011[32] = {
+ -5, 5, 31, 79, 155, 265, 415, 611, 859, 1165, 1535, 1975, 2491, 3089, 3775, 4555, 5435, 6421, 7519, 8735, 10075, 11545, 13151, 14899, 16795, 18845, 21055, 23431, 25979, 28705, 31615, 34715
+};
+TYPE res_test1100[32] = {
+ -13, -37, -81, -151, -253, -393, -577, -811, -1101, -1453, -1873, -2367, -2941, -3601, -4353, -5203, -6157, -7221, -8401, -9703, -11133, -12697, -14401, -16251, -18253, -20413, -22737, -25231, -27901, -30753, -33793, -37027
+};
+TYPE res_test1101[32] = {
+ -17, -43, -89, -161, -265, -407, -593, -829, -1121, -1475, -1897, -2393, -2969, -3631, -4385, -5237, -6193, -7259, -8441, -9745, -11177, -12743, -14449, -16301, -18305, -20467, -22793, -25289, -27961, -30815, -33857, -37093
+};
+TYPE res_test1110[32] = {
+ 17, 43, 89, 161, 265, 407, 593, 829, 1121, 1475, 1897, 2393, 2969, 3631, 4385, 5237, 6193, 7259, 8441, 9745, 11177, 12743, 14449, 16301, 18305, 20467, 22793, 25289, 27961, 30815, 33857, 37093
+};
+TYPE res_test1111[32] = {
+ 13, 37, 81, 151, 253, 393, 577, 811, 1101, 1453, 1873, 2367, 2941, 3601, 4353, 5203, 6157, 7221, 8401, 9703, 11133, 12697, 14401, 16251, 18253, 20413, 22737, 25231, 27901, 30753, 33793, 37027
+};
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_1.h b/gcc/testsuite/gcc.target/i386/l_fma_1.h
new file mode 100644
index 00000000000..4a0fd6e0050
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_1.h
@@ -0,0 +1,133 @@
+
+#ifndef l_fma_1
+#define l_fma_1
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * a[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * a[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * a[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * a[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * a[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * a[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * a[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * a[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * a[i] - b[i];
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_2.h b/gcc/testsuite/gcc.target/i386/l_fma_2.h
new file mode 100644
index 00000000000..fd64b61fdc3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_2.h
@@ -0,0 +1,133 @@
+
+#ifndef l_fma_2
+#define l_fma_2
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * a[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * a[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * a[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * a[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * a[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * a[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * a[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * a[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * a[i] - c[i];
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_3.h b/gcc/testsuite/gcc.target/i386/l_fma_3.h
new file mode 100644
index 00000000000..226af24a0be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_3.h
@@ -0,0 +1,133 @@
+
+#ifndef l_fma_3
+#define l_fma_3
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * b[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * b[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * b[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * b[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * b[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * b[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * b[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * b[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * b[i] - a[i];
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_4.h b/gcc/testsuite/gcc.target/i386/l_fma_4.h
new file mode 100644
index 00000000000..e33fe25ffd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_4.h
@@ -0,0 +1,133 @@
+
+#ifndef l_fma_4
+#define l_fma_4
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * b[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * b[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * b[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * b[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * b[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * b[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * b[i] - c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * b[i] + c[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * b[i] - c[i];
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_5.h b/gcc/testsuite/gcc.target/i386/l_fma_5.h
new file mode 100644
index 00000000000..a754812e387
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_5.h
@@ -0,0 +1,133 @@
+
+#ifndef l_fma_5
+#define l_fma_5
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * c[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * c[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * c[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * c[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * c[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * c[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * c[i] - a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * c[i] + a[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * c[i] - a[i];
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_6.h b/gcc/testsuite/gcc.target/i386/l_fma_6.h
new file mode 100644
index 00000000000..39be29ad376
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_6.h
@@ -0,0 +1,133 @@
+
+#ifndef l_fma_6
+#define l_fma_6
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) + c[i]) * c[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) + c[i]) * c[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = ((a[i] * b[i]) - c[i]) * c[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_noneg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -((a[i] * b[i]) - c[i]) * c[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) + c[i]) * c[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_add_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) + c[i]) * c[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_noneg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = (-(a[i] * b[i]) - c[i]) * c[i] - b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_add (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * c[i] + b[i];
+}
+
+void __attribute__((sseregparm))
+test_neg_sub_neg_sub (TYPE *a, TYPE *b, TYPE *c, TYPE *d, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = -(-(a[i] * b[i]) - c[i]) * c[i] - b[i];
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_1.c b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
new file mode 100644
index 00000000000..3451227b2c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_1.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd213sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub213sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd213sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub213sd" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_2.c b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
new file mode 100644
index 00000000000..e69bd7fe3de
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_2.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_3.c b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
new file mode 100644
index 00000000000..00ed16dad2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_3.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd213sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub213sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd213sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub213sd" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_4.c b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
new file mode 100644
index 00000000000..dbab6430c20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_4.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_5.c b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
new file mode 100644
index 00000000000..210d5670c6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_5.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_6.c b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
new file mode 100644
index 00000000000..68164818fbc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_6.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_1.c b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
new file mode 100644
index 00000000000..c98ba1169f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_1.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd213ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub213ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd213ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub213ss" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_2.c b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
new file mode 100644
index 00000000000..1dafed94e0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_2.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_3.c b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
new file mode 100644
index 00000000000..dbea8fe2714
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_3.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd213ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmsub213ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmadd213ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfnmsub213ss" 4 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_4.c b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
new file mode 100644
index 00000000000..5ff5dcb6da9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_4.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_5.c b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
new file mode 100644
index 00000000000..d83ebcc094e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_5.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_6.c b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
new file mode 100644
index 00000000000..942ed7d9e3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_6.h"
+
+/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_main.h b/gcc/testsuite/gcc.target/i386/l_fma_main.h
new file mode 100644
index 00000000000..a9dc5cd20e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_main.h
@@ -0,0 +1,100 @@
+
+#ifndef l_fma_main
+#define l_fma_main
+
+#if DEBUG
+#include <stdio.h>
+#endif
+
+TYPE m1[32] = {
+ 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
+ };
+TYPE m2[32] = {
+ 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
+ };
+TYPE m3[32] = {
+ 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
+ };
+TYPE m4[32];
+int test_fails = 0;
+
+void
+compare_result(char *title, TYPE *res)
+{
+ int i;
+ int good = 1;
+ for (i =0; i < 32; i++)
+ if (m4[i] != res[i])
+ {
+ if (good)
+ {
+#if DEBUG
+ printf ("!!!! %s miscompare\n", title);
+#endif
+ good = 0;
+ }
+#if DEBUG
+ printf ("res[%d] = %d, must be %d\n", i, (int)res[i], (int) m4[i]);
+#endif
+ }
+ if (!good)
+ test_fails = 1;
+}
+
+static void fma_test ()
+{
+ test_noneg_add_noneg_add (m1, m2, m3, m4, 32);
+ compare_result ("test0000", res_test0000);
+
+ test_noneg_add_noneg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test0001", res_test0001);
+
+ test_noneg_add_neg_add (m1, m2, m3, m4, 32);
+ compare_result ("test0010", res_test0010);
+
+ test_noneg_add_neg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test0011", res_test0011);
+
+ test_noneg_sub_noneg_add (m1, m2, m3, m4, 32);
+ compare_result ("test0100", res_test0100);
+
+ test_noneg_sub_noneg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test0101", res_test0101);
+
+ test_noneg_sub_neg_add (m1, m2, m3, m4, 32);
+ compare_result ("test0110", res_test0110);
+
+ test_noneg_sub_neg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test0111", res_test0111);
+
+ test_neg_add_noneg_add (m1, m2, m3, m4, 32);
+ compare_result ("test1000", res_test1000);
+
+ test_neg_add_noneg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test1001", res_test1001);
+
+ test_neg_add_neg_add (m1, m2, m3, m4, 32);
+ compare_result ("test1010", res_test1010);
+
+ test_neg_add_neg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test1011", res_test1011);
+
+ test_neg_sub_noneg_add (m1, m2, m3, m4, 32);
+ compare_result ("test1100", res_test1100);
+
+ test_neg_sub_noneg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test1101", res_test1101);
+
+ test_neg_sub_neg_add (m1, m2, m3, m4, 32);
+ compare_result ("test1110", res_test1110);
+
+ test_neg_sub_neg_sub (m1, m2, m3, m4, 32);
+ compare_result ("test1111", res_test1111);
+
+ if (test_fails) abort ();
+}
+
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c
new file mode 100644
index 00000000000..f1d3c3a6b44
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_1.h"
+
+#include "fma_run_double_results_1.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c
new file mode 100644
index 00000000000..db85598c106
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_2.h"
+
+#include "fma_run_double_results_2.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c
new file mode 100644
index 00000000000..8043f6fbfbb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_3.h"
+
+#include "fma_run_double_results_3.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c
new file mode 100644
index 00000000000..eef05f58ca9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_4.h"
+
+#include "fma_run_double_results_4.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c
new file mode 100644
index 00000000000..95b4b66d02b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_5.h"
+
+#include "fma_run_double_results_5.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c
new file mode 100644
index 00000000000..24c1a78cdf7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE double
+
+#include "l_fma_6.h"
+
+#include "fma_run_double_results_6.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c
new file mode 100644
index 00000000000..8a046131d0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_1.h"
+
+#include "fma_run_float_results_1.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c
new file mode 100644
index 00000000000..ea6df76f173
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_2.h"
+
+#include "fma_run_float_results_2.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c
new file mode 100644
index 00000000000..5789867d350
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_3.h"
+
+#include "fma_run_float_results_3.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c
new file mode 100644
index 00000000000..377370b8904
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_4.h"
+
+#include "fma_run_float_results_4.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c
new file mode 100644
index 00000000000..8b0cf3f0fdb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_5.h"
+
+#include "fma_run_float_results_5.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c
new file mode 100644
index 00000000000..1300618dac1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fma } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
+
+/* Test that the compiler properly optimizes floating point multiply
+ and add instructions into FMA3 instructions. */
+
+#define TYPE float
+
+#include "l_fma_6.h"
+
+#include "fma_run_float_results_6.h"
+
+#include "fma-check.h"
+#include "l_fma_main.h"
diff --git a/gcc/testsuite/gcc.target/i386/pr50603.c b/gcc/testsuite/gcc.target/i386/pr50603.c
new file mode 100644
index 00000000000..101ef85484d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr50603.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern int *foo;
+
+int
+bar (int x)
+{
+ return foo[x];
+}
+/* { dg-final { scan-assembler-not "lea\[lq\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr50712.c b/gcc/testsuite/gcc.target/i386/pr50712.c
new file mode 100644
index 00000000000..90cc75db346
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr50712.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2" } */
+
+typedef __builtin_va_list __va_list;
+typedef __va_list __gnuc_va_list;
+typedef __gnuc_va_list va_list;
+struct MSVCRT__iobuf { };
+typedef struct MSVCRT__iobuf MSVCRT_FILE;
+typedef union _printf_arg { } printf_arg;
+MSVCRT_FILE MSVCRT__iob[20];
+int pf_print_a (va_list *);
+int __attribute__((__cdecl__))
+MSVCRT_vfprintf_s(MSVCRT_FILE* file, const char *format, va_list valist)
+{
+ if(!((file != ((void *)0))
+ || (MSVCRT__invalid_parameter(((void *)0), ((void *)0),
+ ((void *)0), 0, 0),0)))
+ return -1;
+ return pf_printf_a(&valist);
+}
+int __attribute__((__cdecl__))
+MSVCRT_vprintf_s(const char *format, va_list valist)
+{
+ return MSVCRT_vfprintf_s((MSVCRT__iob+1),format,valist);
+}
+int __attribute__((__cdecl__))
+MSVCRT_fprintf_s(MSVCRT_FILE* file, const char *format, ...)
+{
+ va_list valist;
+ va_start (valist, format);
+ return MSVCRT_vfprintf_s(file, format, valist);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mul-1.c b/gcc/testsuite/gcc.target/i386/sse2-mul-1.c
new file mode 100644
index 00000000000..5c792e8a4aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mul-1.c
@@ -0,0 +1,209 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-options "-O3 -msse2" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse2_test
+#endif
+
+#include CHECK_H
+
+#include <stdlib.h>
+
+#define N 512
+static short a1[N], a2[N], a3[N];
+static unsigned short b1[N], b2[N], b3[N];
+static int c1[N], c2[N], c3[N];
+static unsigned int d1[N], d2[N], d3[N];
+static long long e1[N], e2[N], e3[N];
+static unsigned long long g1[N], g2[N], g3[N];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ a1[i] = a2[i] * a3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ b1[i] = b2[i] * b3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ c1[i] = c2[i] * c3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ d1[i] = d2[i] * d3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ e1[i] = e2[i] * e3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ g1[i] = g2[i] * g3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f7 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ c1[i] = a2[i] * a3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f8 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ d1[i] = (unsigned int) b2[i] * b3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f9 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ e1[i] = (long long) c2[i] * (long long) c3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f10 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ g1[i] = (unsigned long long) d2[i] * (unsigned long long) d3[i];
+}
+
+__attribute__((noinline, noclone)) int
+f11 (void)
+{
+ int i, r = 0;
+ for (i = 0; i < N; ++i)
+ r += a2[i] * a3[i];
+ return r;
+}
+
+__attribute__((noinline, noclone)) unsigned int
+f12 (void)
+{
+ int i;
+ unsigned r = 0;
+ for (i = 0; i < N; ++i)
+ r += (unsigned int) b2[i] * b3[i];
+ return r;
+}
+
+__attribute__((noinline, noclone)) long long
+f13 (void)
+{
+ int i;
+ long long r = 0;
+ for (i = 0; i < N; ++i)
+ r += (long long) c2[i] * (long long) c3[i];
+ return r;
+}
+
+__attribute__((noinline, noclone)) unsigned long long
+f14 (void)
+{
+ int i;
+ unsigned long long r = 0;
+ for (i = 0; i < N; ++i)
+ r += (unsigned long long) d2[i] * (unsigned long long) d3[i];
+ return r;
+}
+
+static void
+TEST (void)
+{
+ int i;
+ int s1 = 0;
+ unsigned int s2 = 0;
+ long long s3 = 0;
+ unsigned long long s4 = 0;
+ for (i = 0; i < N; ++i)
+ {
+ asm volatile ("" : : "r" (&s1) : "memory");
+ asm volatile ("" : : "r" (&s2) : "memory");
+ asm volatile ("" : : "r" (&s3) : "memory");
+ asm volatile ("" : : "r" (&s4) : "memory");
+ b2[i] = (int) random ();
+ b3[i] = (int) random ();
+ a2[i] = b2[i];
+ a3[i] = b3[i];
+ d2[i] = (((int) random ()) << 16) | b2[i];
+ d3[i] = (((int) random ()) << 16) | b3[i];
+ c2[i] = d2[i];
+ c3[i] = d3[i];
+ s1 += a2[i] * a3[i];
+ s2 += (unsigned int) b2[i] * b3[i];
+ s3 += (long long) c2[i] * (long long) c3[i];
+ s4 += (unsigned long long) d2[i] * (unsigned long long) d3[i];
+ }
+ f1 ();
+ f2 ();
+ f3 ();
+ f4 ();
+ f5 ();
+ f6 ();
+ for (i = 0; i < N; ++i)
+ {
+ if (a1[i] != (short) (a2[i] * a3[i]))
+ abort ();
+ if (b1[i] != (unsigned short) (b2[i] * b3[i]))
+ abort ();
+ if (c1[i] != c2[i] * c3[i])
+ abort ();
+ if (d1[i] != d2[i] * d3[i])
+ abort ();
+ if (e1[i] != e2[i] * e3[i])
+ abort ();
+ if (g1[i] != g2[i] * g3[i])
+ abort ();
+ }
+ f7 ();
+ f8 ();
+ f9 ();
+ f10 ();
+ for (i = 0; i < N; ++i)
+ {
+ if (c1[i] != a2[i] * a3[i])
+ abort ();
+ if (d1[i] != b2[i] * b3[i])
+ abort ();
+ if (e1[i] != (long long) c2[i] * (long long) c3[i])
+ abort ();
+ if (g1[i] != (unsigned long long) d2[i] * (unsigned long long) d3[i])
+ abort ();
+ }
+ if (f11 () != s1 || f12 () != s2 || f13 () != s3 || f14 () != s4)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c b/gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c
new file mode 100644
index 00000000000..20d03a515d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-options "-O3 -msse4.1" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c
new file mode 100644
index 00000000000..c9f9c1cdf34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-options "-O3 -msse4.1 -mno-avx2" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+extern void abort (void);
+
+#define N 1024
+short a[N], c, e;
+unsigned short b[N], d, f;
+
+__attribute__((noinline)) short
+vecsmax (void)
+{
+ int i;
+ short r = -32768;
+ for (i = 0; i < N; ++i)
+ if (r < a[i]) r = a[i];
+ return r;
+}
+
+__attribute__((noinline)) unsigned short
+vecumax (void)
+{
+ int i;
+ unsigned short r = 0;
+ for (i = 0; i < N; ++i)
+ if (r < b[i]) r = b[i];
+ return r;
+}
+
+__attribute__((noinline)) short
+vecsmin (void)
+{
+ int i;
+ short r = 32767;
+ for (i = 0; i < N; ++i)
+ if (r > a[i]) r = a[i];
+ return r;
+}
+
+__attribute__((noinline)) unsigned short
+vecumin (void)
+{
+ int i;
+ unsigned short r = 65535;
+ for (i = 0; i < N; ++i)
+ if (r > b[i]) r = b[i];
+ return r;
+}
+
+static void
+TEST (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ a[i] = i - N / 2;
+ b[i] = i + 32768 - N / 2;
+ }
+ a[N / 3] = N;
+ a[2 * N / 3] = -N;
+ b[N / 5] = 32768 + N;
+ b[4 * N / 5] = 32768 - N;
+ if (vecsmax () != N || vecsmin () != -N)
+ abort ();
+ if (vecumax () != 32768 + N || vecumin () != 32768 - N)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c
new file mode 100644
index 00000000000..95c5f059d97
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -msse4.1 -mno-avx2" } */
+
+#include "sse4_1-phminposuw-2.c"
+
+/* { dg-final { scan-assembler "phminposuw\[^\n\r\]*xmm" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sw-1.c b/gcc/testsuite/gcc.target/i386/sw-1.c
new file mode 100644
index 00000000000..483d117ecb7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sw-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fshrink-wrap -fdump-rtl-pro_and_epilogue" } */
+
+#include <string.h>
+
+int c;
+int x[2000];
+__attribute__((regparm(1))) void foo (int a, int b)
+ {
+ int t[200];
+ if (a == 0 || c == 0)
+ return;
+ memcpy (t, x + b, sizeof t);
+ c = t[a];
+ }
+
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */
+/* { dg-final { cleanup-rtl-dump "pro_and_epilogue" } } */
diff --git a/gcc/testsuite/gcc.target/i386/warn-vect-op-1.c b/gcc/testsuite/gcc.target/i386/warn-vect-op-1.c
new file mode 100644
index 00000000000..6fecf926208
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/warn-vect-op-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-options "-mno-sse -Wvector-operation-performance" } */
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[])
+{
+ vector (4, int) v0 = {argc, 1, 15, 38};
+ vector (4, int) v1 = {-4, argc, 2, 11};
+ vector (4, int) res[] =
+ {
+ v0 + v1, /* { dg-warning "expanded piecewise" } */
+ v0 - v1, /* { dg-warning "expanded piecewise" } */
+ v0 > v1, /* { dg-warning "expanded piecewise" } */
+ v0 & v1, /* { dg-warning "expanded in parallel" } */
+ __builtin_shuffle (v0, v1), /* { dg-warning "expanded piecewise" } */
+ __builtin_shuffle (v0, v1, v1) /* { dg-warning "expanded piecewise" } */
+ };
+
+ return res[argc][argc];
+}
diff --git a/gcc/testsuite/gcc.target/i386/warn-vect-op-2.c b/gcc/testsuite/gcc.target/i386/warn-vect-op-2.c
new file mode 100644
index 00000000000..6e631192445
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/warn-vect-op-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-options "-mno-sse -Wvector-operation-performance" } */
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[])
+{
+ vector (16, signed char) v0 = {argc, 1, 15, 38, 12, -1, argc, 2,
+ argc, 1, 15, 38, 12, -1, argc, 2};
+ vector (16, signed char) v1 = {-4, argc, 2, 11, 1, 17, -8, argc,
+ argc, 1, 15, 38, 12, -1, argc, 2};
+ vector (16, signed char) res[] =
+ {
+ v0 + v1, /* { dg-warning "expanded in parallel" } */
+ v0 - v1, /* { dg-warning "expanded in parallel" } */
+ v0 > v1, /* { dg-warning "expanded piecewise" } */
+ v0 & v1, /* { dg-warning "expanded in parallel" } */
+ __builtin_shuffle (v0, v1), /* { dg-warning "expanded piecewise" } */
+ __builtin_shuffle (v0, v1, v1) /* { dg-warning "expanded piecewise" } */
+ };
+
+ return res[argc][argc];
+}
diff --git a/gcc/testsuite/gcc.target/i386/warn-vect-op-3.c b/gcc/testsuite/gcc.target/i386/warn-vect-op-3.c
new file mode 100644
index 00000000000..bdbd8b520b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/warn-vect-op-3.c
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-options "-mno-sse -Wvector-operation-performance" } */
+#define vector(elcount, type) \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[])
+{
+ vector (8, short) v0 = {argc, 1, 15, 38, 12, -1, argc, 2};
+ vector (8, short) v1 = {-4, argc, 2, 11, 1, 17, -8, argc};
+ vector (8, short) res[] =
+ {
+ v0 + v1, /* { dg-warning "expanded in parallel" } */
+ v0 - v1, /* { dg-warning "expanded in parallel" } */
+ v0 > v1, /* { dg-warning "expanded piecewise" } */
+ v0 & v1, /* { dg-warning "expanded in parallel" } */
+ __builtin_shuffle (v0, v1), /* { dg-warning "expanded piecewise" } */
+ __builtin_shuffle (v0, v1, v1) /* { dg-warning "expanded piecewise" } */
+ };
+
+ return res[argc][argc];
+}
diff --git a/gcc/testsuite/gcc.target/i386/xop-mul-1.c b/gcc/testsuite/gcc.target/i386/xop-mul-1.c
new file mode 100644
index 00000000000..47ef1bc02bb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xop-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target xop } */
+/* { dg-options "-O3 -mxop" } */
+
+#ifndef CHECK_H
+#define CHECK_H "xop-check.h"
+#endif
+
+#ifndef TEST
+#define TEST xop_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/mips/abi-o64-long64.c b/gcc/testsuite/gcc.target/mips/abi-o64-long64.c
index 8177f5ab17a..43078f6809a 100644
--- a/gcc/testsuite/gcc.target/mips/abi-o64-long64.c
+++ b/gcc/testsuite/gcc.target/mips/abi-o64-long64.c
@@ -1,2 +1,2 @@
-/* { dg-options "-mabi=o64 -mlong64 addressing=absolute -O2" } */
+/* { dg-options "-mabi=o64 -mlong64 -mno-abicalls -O2" } */
#include "abi-main.h"
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 857cfe87eba..9d666fbaca3 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -588,6 +588,30 @@ proc mips_64bit_abi_p { option } {
return 0
}
+# Return true if the given abi-group option implicitly requires -mlong32.
+# o64 requires this for -mabicalls, but not otherwise; pick the conservative
+# case for simplicity.
+proc mips_long32_abi_p { option } {
+ switch -glob -- $option {
+ -mabi=o64 -
+ -mabi=n32 -
+ -mabi=32 {
+ return 1
+ }
+ }
+ return 0
+}
+
+# Return true if the given abi-group option implicitly requires -mlong64.
+proc mips_long64_abi_p { option } {
+ switch -glob -- $option {
+ -mabi=64 {
+ return 1
+ }
+ }
+ return 0
+}
+
# Check whether the current target supports all the options that the
# current test requires. Return "" if so, otherwise return one of
# the incompatible options. UPSTATUS describes the option status.
@@ -1029,24 +1053,41 @@ proc mips-dg-options { args } {
# -mips16 -mhard-float requires o32 or o64.
# -mips16 PIC requires o32 or o64.
set force_abi 1
+ } elseif { [mips_have_test_option_p options "-mlong32"]
+ && [mips_long64_abi_p $abi] } {
+ set force_abi 1
+ } elseif { [mips_have_test_option_p options "-mlong64"]
+ && [mips_long32_abi_p $abi] } {
+ set force_abi 1
} else {
set force_abi 0
}
if { $gp_size == 32 } {
if { $force_abi || [mips_64bit_abi_p $abi] } {
- mips_make_test_option options "-mabi=32"
+ if { [mips_have_test_option_p options "-mlong64"] } {
+ mips_make_test_option options "-mabi=eabi"
+ mips_make_test_option options "-mgp32"
+ } else {
+ mips_make_test_option options "-mabi=32"
+ }
}
} else {
if { $force_abi || [mips_32bit_abi_p $abi] } {
- # All configurations should have an assembler that
- # supports o64, since it requires the same BFD target
- # vector as o32. In contrast, many assembler
- # configurations do not have n32 or n64 support.
- mips_make_test_option options "-mabi=o64"
+ if { [mips_have_test_option_p options "-mlong64"] } {
+ mips_make_test_option options "-mabi=eabi"
+ mips_make_test_option options "-mgp64"
+ } else {
+ # All configurations should have an assembler that
+ # supports o64, since it requires the same BFD target
+ # vector as o32. In contrast, many assembler
+ # configurations do not have n32 or n64 support.
+ mips_make_test_option options "-mabi=o64"
+ }
}
}
- unset abi
- unset eabi_p
+ set abi_test_option_p [mips_test_option_p options abi]
+ set abi [mips_option options abi]
+ set eabi_p [mips_same_option_p $abi "-mabi=eabi"]
}
# Handle dependencies between the abi options and the post-abi options.
@@ -1070,8 +1111,11 @@ proc mips-dg-options { args } {
mips_make_test_option options "-mno-mips16"
}
}
- unset abi
- unset eabi_p
+ if { [mips_long32_abi_p $abi] } {
+ mips_make_test_option options "-mlong32"
+ } elseif { [mips_long64_abi_p $abi] } {
+ mips_make_test_option options "-mlong64"
+ }
}
# Handle dependencies between the arch option and the post-arch options.
diff --git a/gcc/testsuite/gcc.target/mips/stack-1.c b/gcc/testsuite/gcc.target/mips/stack-1.c
new file mode 100644
index 00000000000..3d495453dd7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/stack-1.c
@@ -0,0 +1,11 @@
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "addiu\t(\\\$sp,)?\\\$sp,\[1-9\]" } } */
+/* { dg-final { scan-assembler "\tlw\t" } } */
+/* { dg-final { scan-assembler-not "addiu\t(\\\$sp,)?\\\$sp,\[1-9\].*\tlw\t" } } */
+
+int foo (int y)
+{
+ volatile int a = y;
+ volatile int *volatile b = &a;
+ return *b;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c
index c83c58298bd..3203704be7c 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mcpu=power6 -maltivec -ffast-math" } */
/* { dg-final { scan-assembler-times "vmaddfp" 2 } } */
/* { dg-final { scan-assembler-times "fmadd " 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c
index 44da6e76bc4..35836eec234 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mcpu=power6 -maltivec -ffast-math -ffp-contract=off" } */
/* { dg-final { scan-assembler-times "vmaddfp" 1 } } */
/* { dg-final { scan-assembler-times "fmadd " 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c
index 97243afb7c4..e5ba874e7ea 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c
@@ -1,5 +1,6 @@
/* { dg-do run { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mcpu=power5 -std=c99" } */
#ifndef __FP_FAST_FMA
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c
index ec0c3d74075..f6e7e4ce561 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mcpu=power6 -ffast-math" } */
/* { dg-final { scan-assembler-times "fmadd" 1 } } */
/* { dg-final { scan-assembler-times "fmsub " 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c
index 2eebbb42cdd..23b3d1e15e8 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mcpu=power5+ -ffast-math" } */
/* { dg-final { scan-assembler-not "xsrdpiz" } } */
/* { dg-final { scan-assembler "friz" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c
index 6196162a2ff..bf12113d28c 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mcpu=power5 -ffast-math" } */
/* { dg-final { scan-assembler-not "lfiwax" } } */
/* { dg-final { scan-assembler-not "lfiwzx" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c
index 007c8644a0c..808cbc39078 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -mcpu=power5 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 2 } } */
/* { dg-final { scan-assembler-not "fctiwuz" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c
index b5410f60ea5..f841d7ee073 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -mcpu=750 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 6 } } */
/* { dg-final { scan-assembler-not "fctiwuz" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-pow.c b/gcc/testsuite/gcc.target/powerpc/ppc-pow.c
index e88125c1d98..ee09d690f50 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-pow.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-pow.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -ffast-math -mcpu=power6" } */
/* { dg-final { scan-assembler-times "fsqrt" 3 } } */
/* { dg-final { scan-assembler-times "fmul" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-1.c b/gcc/testsuite/gcc.target/powerpc/recip-1.c
index 590881bb892..4ae0c4f119f 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power6" } */
/* { dg-final { scan-assembler-times "frsqrte" 2 } } */
/* { dg-final { scan-assembler-times "fmsub" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-2.c b/gcc/testsuite/gcc.target/powerpc/recip-2.c
index 3e64c07578f..5c9fbbda510 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power5" } */
/* { dg-final { scan-assembler-times "frsqrtes" 1 } } */
/* { dg-final { scan-assembler-times "fmsubs" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-3.c b/gcc/testsuite/gcc.target/powerpc/recip-3.c
index 40658818047..905e793952e 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-3.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power7" } */
/* { dg-final { scan-assembler-times "xsrsqrtedp" 1 } } */
/* { dg-final { scan-assembler-times "xsmsub.dp\|fmsub\ " 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-4.c b/gcc/testsuite/gcc.target/powerpc/recip-4.c
index bd496d70e25..35eef6f0f0f 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-4.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mrecip -ffast-math -mcpu=power7 -fno-unroll-loops" } */
/* { dg-final { scan-assembler-times "xvrsqrtedp" 1 } } */
/* { dg-final { scan-assembler-times "xvmsub.dp" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-5.c b/gcc/testsuite/gcc.target/powerpc/recip-5.c
index 4a9c496201a..0b3823cfa51 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-5.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mrecip=all -ffast-math -mcpu=power7 -fno-unroll-loops" } */
/* { dg-final { scan-assembler-times "xvredp" 4 } } */
/* { dg-final { scan-assembler-times "xvresp" 5 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/warn-1.c b/gcc/testsuite/gcc.target/powerpc/warn-1.c
index c00aff08c6e..f4cb4372fdb 100644
--- a/gcc/testsuite/gcc.target/powerpc/warn-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/warn-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O -mvsx -mno-altivec" } */
/* { dg-warning "-mvsx and -mno-altivec are incompatible" "" { target *-*-* } 1 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/warn-2.c b/gcc/testsuite/gcc.target/powerpc/warn-2.c
index 0a9fa1e3ff3..e8c9096f774 100644
--- a/gcc/testsuite/gcc.target/powerpc/warn-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/warn-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O -mcpu=power7 -mno-altivec" } */
/* { dg-warning "-mno-altivec disables vsx" "" { target *-*-* } 1 } */
diff --git a/gcc/testsuite/gcc.target/s390/20090223-1.c b/gcc/testsuite/gcc.target/s390/20090223-1.c
index 443ccb9aa69..1bf0f2fe8f3 100644
--- a/gcc/testsuite/gcc.target/s390/20090223-1.c
+++ b/gcc/testsuite/gcc.target/s390/20090223-1.c
@@ -3,7 +3,7 @@
register asm ("0"). */
/* { dg-do run } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -Wno-attributes" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/sparc/cmask.c b/gcc/testsuite/gcc.target/sparc/cmask.c
index b3168ec321d..d1be910f5e0 100644
--- a/gcc/testsuite/gcc.target/sparc/cmask.c
+++ b/gcc/testsuite/gcc.target/sparc/cmask.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-options "-mvis3" } */
void test_cm8 (long x)
{
diff --git a/gcc/testsuite/gcc.target/sparc/fand.c b/gcc/testsuite/gcc.target/sparc/fand.c
index 3194c921ccd..b0589bdbb3c 100644
--- a/gcc/testsuite/gcc.target/sparc/fand.c
+++ b/gcc/testsuite/gcc.target/sparc/fand.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return foo1_8 () & foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return a & b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return foo1_16 () & foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return a & b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,12 +38,9 @@ vec32 fun32(void)
return foo1_32 () & foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return a & b;
}
-#endif
-/* { dg-final { scan-assembler-times "fand\t%" 3 } } */
+/* { dg-final { scan-assembler-times "fand\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fandnot.c b/gcc/testsuite/gcc.target/sparc/fandnot.c
index 41db849c239..005486385fa 100644
--- a/gcc/testsuite/gcc.target/sparc/fandnot.c
+++ b/gcc/testsuite/gcc.target/sparc/fandnot.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~foo1_8 () & foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return ~a & b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return ~foo1_16 () & foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return ~a & b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,13 +38,10 @@ vec32 fun32(void)
return ~foo1_32 () & foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return ~a & b;
}
-#endif
/* This should be transformed into ~b & a. */
@@ -59,38 +50,29 @@ vec8 fun8b(void)
return foo1_8 () & ~foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2b(vec8 a, vec8 b)
{
return a & ~b;
}
-#endif
vec16 fun16b(void)
{
return foo1_16 () & ~foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2b(vec16 a, vec16 b)
{
return a & ~b;
}
-#endif
vec32 fun32b(void)
{
return foo1_32 () & ~foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2b(vec32 a, vec32 b)
{
return a & ~b;
}
-#endif
-/* { dg-final { scan-assembler-times "fandnot1\t%" 6 } } */
+/* { dg-final { scan-assembler-times "fandnot1\t%" 12 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fhalve.c b/gcc/testsuite/gcc.target/sparc/fhalve.c
new file mode 100644
index 00000000000..b8f0745afc9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fhalve.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
+
+float test_fhadds (float x, float y)
+{
+ return __builtin_vis_fhadds (x, y);
+}
+
+double test_fhaddd (double x, double y)
+{
+ return __builtin_vis_fhaddd (x, y);
+}
+
+float test_fhsubs (float x, float y)
+{
+ return __builtin_vis_fhsubs (x, y);
+}
+
+double test_fhsubd (double x, double y)
+{
+ return __builtin_vis_fhsubd (x, y);
+}
+
+float test_fnhadds (float x, float y)
+{
+ return __builtin_vis_fnhadds (x, y);
+}
+
+double test_fnhaddd (double x, double y)
+{
+ return __builtin_vis_fnhaddd (x, y);
+}
+
+/* { dg-final { scan-assembler "fhadds\t%" } } */
+/* { dg-final { scan-assembler "fhaddd\t%" } } */
+/* { dg-final { scan-assembler "fhsubs\t%" } } */
+/* { dg-final { scan-assembler "fhsubd\t%" } } */
+/* { dg-final { scan-assembler "fnhadds\t%" } } */
+/* { dg-final { scan-assembler "fnhaddd\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fnegop.c b/gcc/testsuite/gcc.target/sparc/fnegop.c
new file mode 100644
index 00000000000..cbdf28f4c60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fnegop.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mvis3" } */
+
+float test_fnadds(float x, float y)
+{
+ return -(x + y);
+}
+
+double test_fnaddd(double x, double y)
+{
+ return -(x + y);
+}
+
+float test_fnmuls(float x, float y)
+{
+ return -(x * y);
+}
+
+double test_fnmuld(double x, double y)
+{
+ return -(x * y);
+}
+
+double test_fnsmuld(float x, float y)
+{
+ return -((double)x * (double)y);
+}
+
+/* { dg-final { scan-assembler "fnadds\t%" } } */
+/* { dg-final { scan-assembler "fnaddd\t%" } } */
+/* { dg-final { scan-assembler "fnmuls\t%" } } */
+/* { dg-final { scan-assembler "fnmuld\t%" } } */
+/* { dg-final { scan-assembler "fnsmuld\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fnot.c b/gcc/testsuite/gcc.target/sparc/fnot.c
index dceee52f7da..c0ddc931fbb 100644
--- a/gcc/testsuite/gcc.target/sparc/fnot.c
+++ b/gcc/testsuite/gcc.target/sparc/fnot.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~foo1_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a)
{
foo2_8 (~a);
}
-#endif
extern vec16 foo1_16(void);
extern void foo2_16(vec16);
@@ -29,13 +26,10 @@ vec16 fun16(void)
return ~foo1_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a)
{
foo2_16 (~a);
}
-#endif
extern vec32 foo1_32(void);
extern void foo2_32(vec32);
@@ -45,12 +39,9 @@ vec32 fun32(void)
return ~foo1_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a)
{
foo2_32 (~a);
}
-#endif
-/* { dg-final { scan-assembler-times "fnot1\t%" 3 } } */
+/* { dg-final { scan-assembler-times "fnot1\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/for.c b/gcc/testsuite/gcc.target/sparc/for.c
index 7348dce2035..3da4bc23771 100644
--- a/gcc/testsuite/gcc.target/sparc/for.c
+++ b/gcc/testsuite/gcc.target/sparc/for.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return foo1_8 () | foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return a | b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return foo1_16 () | foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return a | b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,12 +38,9 @@ vec32 fun32(void)
return foo1_32 () | foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return a | b;
}
-#endif
-/* { dg-final { scan-assembler-times "for\t%" 3 } } */
+/* { dg-final { scan-assembler-times "for\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fornot.c b/gcc/testsuite/gcc.target/sparc/fornot.c
index 09fdb4f98f3..2daa96e0a09 100644
--- a/gcc/testsuite/gcc.target/sparc/fornot.c
+++ b/gcc/testsuite/gcc.target/sparc/fornot.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~foo1_8 () | foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return ~a | b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return ~foo1_16 () | foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return ~a | b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,14 +38,10 @@ vec32 fun32(void)
return ~foo1_32 () | foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return ~a | b;
}
-#endif
-
/* This should be transformed into ~b | a. */
vec8 fun8b(void)
@@ -59,38 +49,29 @@ vec8 fun8b(void)
return foo1_8 () | ~foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2b(vec8 a, vec8 b)
{
return a | ~b;
}
-#endif
vec16 fun16b(void)
{
return foo1_16 () | ~foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2b(vec16 a, vec16 b)
{
return a | ~b;
}
-#endif
vec32 fun32b(void)
{
return foo1_32 () | ~foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2b(vec32 a, vec32 b)
{
return a | ~b;
}
-#endif
-/* { dg-final { scan-assembler-times "fornot1\t%" 6 } } */
+/* { dg-final { scan-assembler-times "fornot1\t%" 12 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fpadds.c b/gcc/testsuite/gcc.target/sparc/fpadds.c
index d0704e03eda..9b1027d5fca 100644
--- a/gcc/testsuite/gcc.target/sparc/fpadds.c
+++ b/gcc/testsuite/gcc.target/sparc/fpadds.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-options "-mvis3" } */
typedef int __v2si __attribute__((vector_size(8)));
typedef int __v1si __attribute__((vector_size(4)));
typedef short __v4hi __attribute__((vector_size(8)));
diff --git a/gcc/testsuite/gcc.target/sparc/fshift.c b/gcc/testsuite/gcc.target/sparc/fshift.c
index a12df0451cb..1f032151c16 100644
--- a/gcc/testsuite/gcc.target/sparc/fshift.c
+++ b/gcc/testsuite/gcc.target/sparc/fshift.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-options "-mvis3" } */
typedef int __v2si __attribute__((vector_size(8)));
typedef short __v4hi __attribute__((vector_size(8)));
diff --git a/gcc/testsuite/gcc.target/sparc/fucmp.c b/gcc/testsuite/gcc.target/sparc/fucmp.c
index 7f291c3e7ed..6e8f1b3418e 100644
--- a/gcc/testsuite/gcc.target/sparc/fucmp.c
+++ b/gcc/testsuite/gcc.target/sparc/fucmp.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-options "-mvis3" } */
typedef unsigned char vec8 __attribute__((vector_size(8)));
long test_fucmple8 (vec8 a, vec8 b)
diff --git a/gcc/testsuite/gcc.target/sparc/fxnor.c b/gcc/testsuite/gcc.target/sparc/fxnor.c
index a685e08e04c..e635d65fdc4 100644
--- a/gcc/testsuite/gcc.target/sparc/fxnor.c
+++ b/gcc/testsuite/gcc.target/sparc/fxnor.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~(foo1_8 () ^ foo2_8 ());
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return ~(a ^ b);
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return ~(foo1_16 () ^ foo2_16 ());
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return ~(a ^ b);
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,13 +38,10 @@ vec32 fun32(void)
return ~(foo1_32 () ^ foo2_32 ());
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return ~(a ^ b);
}
-#endif
/* This should be transformed into ~(b ^ a). */
@@ -59,38 +50,29 @@ vec8 fun8b(void)
return foo1_8 () ^ ~foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2b(vec8 a, vec8 b)
{
return a ^ ~b;
}
-#endif
vec16 fun16b(void)
{
return foo1_16 () ^ ~foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2b(vec16 a, vec16 b)
{
return a ^ ~b;
}
-#endif
vec32 fun32b(void)
{
return foo1_32 () ^ ~foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2b(vec32 a, vec32 b)
{
return a ^ ~b;
}
-#endif
-/* { dg-final { scan-assembler-times "fxnor\t%" 6 } } */
+/* { dg-final { scan-assembler-times "fxnor\t%" 12 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fxor.c b/gcc/testsuite/gcc.target/sparc/fxor.c
index 581b37b54fb..6ca2f76a1eb 100644
--- a/gcc/testsuite/gcc.target/sparc/fxor.c
+++ b/gcc/testsuite/gcc.target/sparc/fxor.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return foo1_8 () ^ foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return a ^ b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return foo1_16 () ^ foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return a ^ b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,12 +38,9 @@ vec32 fun32(void)
return foo1_32 () ^ foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return a ^ b;
}
-#endif
-/* { dg-final { scan-assembler-times "fxor\t%" 3 } } */
+/* { dg-final { scan-assembler-times "fxor\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/lzd.c b/gcc/testsuite/gcc.target/sparc/lzd.c
new file mode 100644
index 00000000000..bc2b8522be8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/lzd.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
+int test_clz(int a)
+{
+ return __builtin_clz(a);
+}
+
+long test_clzl(long a)
+{
+ return __builtin_clzl(a);
+}
+
+long long test_clzll(long long a)
+{
+ return __builtin_clzll(a);
+}
+
+/* { dg-final { scan-assembler-times "lzd\t%" 3 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/popc.c b/gcc/testsuite/gcc.target/sparc/popc.c
new file mode 100644
index 00000000000..5442a610fa2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/popc.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=niagara2" } */
+int test_popcount(int a)
+{
+ return __builtin_popcount(a);
+}
+
+long test_popcountl(long a)
+{
+ return __builtin_popcountl(a);
+}
+
+long long test_popcountll(long long a)
+{
+ return __builtin_popcountll(a);
+}
+
+/* { dg-final { scan-assembler-times "popc\t%" 3 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/sparc.exp b/gcc/testsuite/gcc.target/sparc/sparc.exp
index 9658d08bc9c..51c9c16ecb7 100644
--- a/gcc/testsuite/gcc.target/sparc/sparc.exp
+++ b/gcc/testsuite/gcc.target/sparc/sparc.exp
@@ -24,6 +24,17 @@ if ![istarget sparc*-*-*] then {
# Load support procs.
load_lib gcc-dg.exp
+# Return 1 if vis3 instructions can be compiled.
+proc check_effective_target_vis3 { } {
+ return [check_no_compiler_messages vis3 object {
+ long long
+ _vis3_fpadd64 (long long __X, long long __Y)
+ {
+ return __builtin_vis_fpadd64 (__X, __Y);
+ }
+ } "-mcpu=niagara3 -mvis" ]
+}
+
# If a testcase doesn't have special options, use these.
global DEFAULT_CFLAGS
if ![info exists DEFAULT_CFLAGS] then {
diff --git a/gcc/testsuite/gcc.target/sparc/vis3misc.c b/gcc/testsuite/gcc.target/sparc/vis3misc.c
index 8a9535e8fb5..7286d705dd5 100644
--- a/gcc/testsuite/gcc.target/sparc/vis3misc.c
+++ b/gcc/testsuite/gcc.target/sparc/vis3misc.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-options "-mvis3" } */
typedef int __v2si __attribute__((vector_size(8)));
typedef short __v4hi __attribute__((vector_size(8)));
typedef unsigned char __v8qi __attribute__((vector_size(8)));
diff --git a/gcc/testsuite/gcc.target/sparc/xmul.c b/gcc/testsuite/gcc.target/sparc/xmul.c
new file mode 100644
index 00000000000..a432ee1fec1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/xmul.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
+typedef long long int64_t;
+
+int64_t test_umulxhi (int64_t x, int64_t y)
+{
+ return __builtin_vis_umulxhi (x, y);
+}
+
+int64_t test_xmulx (int64_t x, int64_t y)
+{
+ return __builtin_vis_xmulx (x, y);
+}
+
+int64_t test_xmulxhi (int64_t x, int64_t y)
+{
+ return __builtin_vis_xmulxhi (x, y);
+}
+
+/* { dg-final { scan-assembler "umulxhi\t%" } } */
+/* { dg-final { scan-assembler "xmulx\t%" } } */
+/* { dg-final { scan-assembler "xmulxhi\t%" } } */
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90 b/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90
index 861f8c7cfd8..5a5771c7a0f 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90
@@ -1,10 +1,10 @@
! { dg-do compile }
-! { dg-options "-std=f2008tr" }
+! { dg-options "-std=f2008ts" }
!
! PR fortran/48858
! PR fortran/48820
!
-! OPTIONAL + BIND(C) is allowed since TR 29113
+! OPTIONAL + BIND(C) is allowed since TS 29113
!
! VALID
@@ -13,20 +13,20 @@ subroutine sub(z) bind(C)
integer(c_int), value :: z
end subroutine sub
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2(z) bind(C)
use iso_c_binding
integer(c_int), optional :: z
end subroutine sub2
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2a(z) bind(C)
use iso_c_binding
integer(c_int) :: z
optional :: z
end subroutine sub2a
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2b(z) bind(C)
use iso_c_binding
optional :: z
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90 b/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90
index 374f8129136..3917b9d3001 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90
@@ -4,7 +4,7 @@
! PR fortran/48858
! PR fortran/48820
!
-! OPTIONAL + BIND(C) is allowed since TR 29113
+! OPTIONAL + BIND(C) is allowed since TS 29113
!
! VALID
@@ -13,20 +13,20 @@ subroutine sub(z) bind(C)
integer(c_int), value :: z
end subroutine sub
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2(z) bind(C) ! { dg-error "with OPTIONAL attribute in procedure" }
use iso_c_binding
integer(c_int), optional :: z
end subroutine sub2
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2a(z) bind(C) ! { dg-error "with OPTIONAL attribute in procedure" }
use iso_c_binding
integer(c_int) :: z
optional :: z
end subroutine sub2a
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2b(z) bind(C) ! { dg-error "with OPTIONAL attribute in procedure" }
use iso_c_binding
optional :: z
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90 b/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90
index 703ab5f19fa..a6ebd5833c1 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90
@@ -4,7 +4,7 @@
! PR fortran/48858
! PR fortran/48820
!
-! TR 29113: BIND(C) with OPTIONAL
+! TS 29113: BIND(C) with OPTIONAL
!
module m
use iso_c_binding
diff --git a/gcc/testsuite/gfortran.dg/c_kind_tests_3.f03 b/gcc/testsuite/gfortran.dg/c_kind_tests_3.f03
new file mode 100644
index 00000000000..5d5f3ab195f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_kind_tests_3.f03
@@ -0,0 +1,11 @@
+! { dg-do compile }
+!
+! PR 47023: [4.6/4.7 regression] C_Sizeof: Rejects valid code
+!
+! Contributed by <florian.rathgeber@gmail.com>
+
+ use iso_c_binding
+ real(c_double) x
+ print *, c_sizeof(x)
+ print *, c_sizeof(0.0_c_double)
+end
diff --git a/gcc/testsuite/gfortran.dg/c_sizeof_2.f90 b/gcc/testsuite/gfortran.dg/c_sizeof_2.f90
index e163797470f..e3911facf6a 100644
--- a/gcc/testsuite/gfortran.dg/c_sizeof_2.f90
+++ b/gcc/testsuite/gfortran.dg/c_sizeof_2.f90
@@ -2,7 +2,7 @@
! { dg-options "-std=f2003 -Wall -Wno-conversion" }
! Support F2008's c_sizeof()
!
-USE ISO_C_BINDING, only: C_SIZE_T, c_sizeof ! { dg-error "new in Fortran 2008" }
+USE ISO_C_BINDING, only: C_SIZE_T, c_sizeof ! { dg-error "is not in the selected standard" }
integer(C_SIZE_T) :: i
i = c_sizeof(i)
end
diff --git a/gcc/testsuite/gfortran.dg/class_46.f03 b/gcc/testsuite/gfortran.dg/class_46.f03
new file mode 100644
index 00000000000..4719c252f63
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_46.f03
@@ -0,0 +1,18 @@
+! { dg-do run }
+!
+! PR 50625: [4.6/4.7 Regression][OOP] ALLOCATABLE attribute lost for module CLASS variables
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+
+module m
+type t
+end type t
+class(t), allocatable :: x
+end module m
+
+use m
+implicit none
+if (allocated(x)) call abort()
+end
+
+! { dg-final { cleanup-modules "m" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray/subobject_1.f90 b/gcc/testsuite/gfortran.dg/coarray/subobject_1.f90
new file mode 100644
index 00000000000..02536866b4d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/subobject_1.f90
@@ -0,0 +1,43 @@
+! { dg-do run }
+!
+! PR fortran/50420
+! Coarray subobjects were not accepted as valid coarrays
+
+ integer :: i
+ integer, parameter :: la = 4, lb = 5, lc = 8
+ integer, parameter :: init(la) = -4 + (/ (i, i=1,la) /)
+
+ type t
+ integer :: i
+ end type t
+ type t2
+ type(t), allocatable :: a[:]
+ end type t2
+ type t3
+ type(t), allocatable :: a(:)[:]
+ end type t3
+
+ type(t2) :: b
+ type(t3) :: c
+
+ allocate(b%a[lb:*])
+ b%a%i = 7
+ if (b%a%i /= 7) call abort
+ if (any (lcobound(b%a) /= (/ lb /))) call abort
+ if (ucobound(b%a, dim=1) /= this_image() + lb - 1) call abort
+ if (any (lcobound(b%a%i) /= (/ lb /))) call abort
+ if (ucobound(b%a%i, dim=1) /= this_image() + lb - 1) call abort
+ allocate(c%a(la)[lc:*])
+ c%a%i = init
+ if (any(c%a%i /= init)) call abort
+ if (any (lcobound(c%a) /= (/ lc /))) call abort
+ if (ucobound(c%a, dim=1) /= this_image() + lc - 1) call abort
+ if (any (lcobound(c%a%i) /= (/ lc /))) call abort
+ if (ucobound(c%a%i, dim=1) /= this_image() + lc - 1) call abort
+ if (c%a(2)%i /= init(2)) call abort
+ if (any (lcobound(c%a(2)) /= (/ lc /))) call abort
+ if (ucobound(c%a(2), dim=1) /= this_image() + lc - 1) call abort
+ if (any (lcobound(c%a(2)%i) /= (/ lc /))) call abort
+ if (ucobound(c%a(2)%i, dim=1) /= this_image() + lc - 1) call abort
+ deallocate(b%a, c%a)
+end
diff --git a/gcc/testsuite/gfortran.dg/coarray_subobject_1.f90 b/gcc/testsuite/gfortran.dg/coarray_subobject_1.f90
new file mode 100644
index 00000000000..52c65e149b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_subobject_1.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+!
+! PR fortran/50420
+! Coarray subobjects were not accepted as valid coarrays
+! They should still be rejected if one of the component reference is allocatable
+! or pointer
+
+type t
+ integer :: i
+end type t
+type t2
+ type(t), allocatable :: a
+ type(t), pointer :: c
+end type t2
+type(t2) :: b[5:*]
+allocate(b%a)
+allocate(b%c)
+b%a%i = 7
+b%c%i = 13
+if (b%a%i /= 7) call abort
+if (any (lcobound(b%a) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%a, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+if (any (lcobound(b%a%i) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%a%i, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+if (b%c%i /= 13) call abort
+if (any (lcobound(b%c) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%c, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+if (any (lcobound(b%c%i) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%c%i, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+end
diff --git a/gcc/testsuite/gfortran.dg/common_14.f90 b/gcc/testsuite/gfortran.dg/common_14.f90
index aced168c655..892e4a5705f 100644
--- a/gcc/testsuite/gfortran.dg/common_14.f90
+++ b/gcc/testsuite/gfortran.dg/common_14.f90
@@ -1,4 +1,5 @@
! { dg-do compile }
+! { dg-options "-Wno-align-commons" }
!
! PR fortran/45044
!
diff --git a/gcc/testsuite/gfortran.dg/common_16.f90 b/gcc/testsuite/gfortran.dg/common_16.f90
new file mode 100644
index 00000000000..3314e80ef9d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/common_16.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-pedantic -mdalign" { target sh*-*-* } }
+!
+! PR fortran/50273
+!
+subroutine test()
+ character :: a
+ integer :: b
+ character :: c
+ common /global_var/ a, b, c ! { dg-warning "Padding of 3 bytes required before 'b' in COMMON" }
+ print *, a, b, c
+end subroutine test
diff --git a/gcc/testsuite/gfortran.dg/dummy_procedure_6.f90 b/gcc/testsuite/gfortran.dg/dummy_procedure_6.f90
new file mode 100644
index 00000000000..fa9ebfe3546
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dummy_procedure_6.f90
@@ -0,0 +1,71 @@
+! { dg-do compile }
+!
+! PR 35381: [F95] Shape mismatch check missing for dummy procedure argument
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+module m
+
+ implicit none
+
+contains
+
+ ! constant array bounds
+
+ subroutine s1(a)
+ integer :: a(1:2)
+ end subroutine
+
+ subroutine s2(a)
+ integer :: a(2:3)
+ end subroutine
+
+ subroutine s3(a)
+ integer :: a(2:4)
+ end subroutine
+
+ ! non-constant array bounds
+
+ subroutine t1(a,b)
+ integer :: b
+ integer :: a(1:b,1:b)
+ end subroutine
+
+ subroutine t2(a,b)
+ integer :: b
+ integer :: a(1:b,2:b+1)
+ end subroutine
+
+ subroutine t3(a,b)
+ integer :: b
+ integer :: a(1:b,1:b+1)
+ end subroutine
+
+end module
+
+
+program test
+ use m
+ implicit none
+
+ call foo(s1) ! legal
+ call foo(s2) ! legal
+ call foo(s3) ! { dg-error "Shape mismatch in dimension" }
+
+ call bar(t1) ! legal
+ call bar(t2) ! legal
+ call bar(t3) ! { dg-error "Shape mismatch in dimension" }
+
+contains
+
+ subroutine foo(f)
+ procedure(s1) :: f
+ end subroutine
+
+ subroutine bar(f)
+ procedure(t1) :: f
+ end subroutine
+
+end program
+
+! { dg-final { cleanup-modules "m" } }
diff --git a/gcc/testsuite/gfortran.dg/elemental_args_check_4.f90 b/gcc/testsuite/gfortran.dg/elemental_args_check_4.f90
new file mode 100644
index 00000000000..2c50f58de2d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/elemental_args_check_4.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+!
+! PR 50547: dummy procedure argument of PURE shall be PURE
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+elemental function fun (sub)
+ interface
+ pure subroutine sub ! { dg-error "not allowed in elemental procedure" }
+ end subroutine
+ end interface
+end function
diff --git a/gcc/testsuite/gfortran.dg/forall_15.f90 b/gcc/testsuite/gfortran.dg/forall_15.f90
new file mode 100644
index 00000000000..c875e033312
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/forall_15.f90
@@ -0,0 +1,26 @@
+! { dg-do run }
+! { dg-options "-ffrontend-optimize -fdump-tree-original" }
+! PR 50564 - this used to ICE with front end optimization.
+! Original test case by Andrew Benson.
+program test
+ implicit none
+ double precision, dimension(2) :: timeSteps, control
+ integer :: iTime
+ double precision :: ratio
+ double precision :: a
+
+ ratio = 0.7d0
+ control(1) = ratio**(dble(1)-0.5d0)-ratio**(dble(1)-1.5d0)
+ control(2) = ratio**(dble(2)-0.5d0)-ratio**(dble(2)-1.5d0)
+ forall(iTime=1:2)
+ timeSteps(iTime)=ratio**(dble(iTime)-0.5d0)-ratio**(dble(iTime)-1.5d0)
+ end forall
+ if (any(abs(timesteps - control) > 1d-10)) call abort
+
+ ! Make sure we still do the front-end optimization after a forall
+ a = cos(ratio)*cos(ratio) + sin(ratio)*sin(ratio)
+ if (abs(a-1.d0) > 1d-10) call abort
+end program test
+! { dg-final { scan-tree-dump-times "__builtin_cos" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_sin" 1 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_class.f03 b/gcc/testsuite/gfortran.dg/iso_c_binding_class.f03
new file mode 100644
index 00000000000..bfb05bcc89b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_class.f03
@@ -0,0 +1,15 @@
+! { dg-do compile }
+!
+! PR 47023: C_Sizeof: Rejects valid code
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+
+ use iso_c_binding
+ type t
+ integer(c_int) :: i
+ end type t
+contains
+ subroutine test(a) bind(c) ! { dg-error "is not C interoperable" }
+ class(t) :: a
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_param_1.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_param_1.f90
new file mode 100644
index 00000000000..dae9cc3703f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_param_1.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-std=f2008" }
+!
+! Check that the GNU additions to ISO_C_Binding are properly diagnosed
+!
+use, intrinsic :: iso_c_binding, only: c_int128_t ! { dg-error "is not in the selected standard" }
+use, intrinsic :: iso_c_binding, only: c_int_least128_t ! { dg-error "is not in the selected standard" }
+use, intrinsic :: iso_c_binding, only: c_int_fast128_t ! { dg-error "is not in the selected standard" }
+use, intrinsic :: iso_c_binding, only: c_float128 ! { dg-error "is not in the selected standard" }
+use, intrinsic :: iso_c_binding, only: c_float128_complex ! { dg-error "is not in the selected standard" }
+implicit none
+end
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_param_2.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_param_2.f90
new file mode 100644
index 00000000000..7b78743452a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_param_2.f90
@@ -0,0 +1,20 @@
+! { dg-do compile }
+! { dg-options "-O -fdump-tree-optimized" }
+!
+! Check that the GNU additions to ISO_C_Binding are accepted
+!
+use, intrinsic :: iso_c_binding, only: c_int128_t
+use, intrinsic :: iso_c_binding, only: c_int_least128_t
+use, intrinsic :: iso_c_binding, only: c_int_fast128_t
+use, intrinsic :: iso_c_binding, only: c_float128
+use, intrinsic :: iso_c_binding, only: c_float128_complex
+implicit none
+if (c_int128_t >= 0 .and. c_int128_t /= 16) call unreachable()
+if (c_int_least128_t >= 0 .and. c_int_least128_t < 16) call unreachable()
+if (c_int_fast128_t >= 0 .and. c_int_fast128_t < 16) call unreachable()
+if (c_float128 >= 0 .and. c_float128 /= 16) call unreachable()
+if (c_float128_complex >= 0 .and. c_float128_complex /= 16) call unreachable()
+end
+
+! { dg-final { scan-tree-dump-times "unreachable" 0 "optimized" } }
+! { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/kind_tests_4.f90 b/gcc/testsuite/gfortran.dg/kind_tests_4.f90
new file mode 100644
index 00000000000..050c15a282b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/kind_tests_4.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+!
+! PR 50752: [4.7 Regression] ICE in match_kind_param
+!
+! Contributed by Joost VandeVondele <Joost.VandeVondele@pci.uzh.ch>
+
+rPos=0.0_dp ! { dg-error "Missing kind-parameter" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pointer_check_11.f90 b/gcc/testsuite/gfortran.dg/pointer_check_11.f90
new file mode 100644
index 00000000000..b6aa79ae260
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_check_11.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+! { dg-options "-fcheck=all" }
+!
+! { dg-shouldfail "Pointer check" }
+! { dg-output "Fortran runtime error: Pointer actual argument 'y' is not associated" }
+!
+!
+! PR fortran/50718
+!
+! Was failing (ICE) with -fcheck=pointer if the dummy had the value attribute.
+
+type t
+ integer :: p
+end type t
+
+type(t), pointer :: y => null()
+
+call sub(y) ! Invalid: Nonassociated pointer
+
+contains
+ subroutine sub (x)
+ type(t), value :: x
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/pointer_check_12.f90 b/gcc/testsuite/gfortran.dg/pointer_check_12.f90
new file mode 100644
index 00000000000..cfef70e5999
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_check_12.f90
@@ -0,0 +1,22 @@
+! { dg-do run }
+! { dg-options "-fcheck=all" }
+!
+! { dg-shouldfail "Pointer check" }
+! { dg-output "Fortran runtime error: Pointer actual argument 'p' is not associated" }
+!
+! PR fortran/50718
+!
+! Was failing with -fcheck=pointer: Segfault at run time
+
+integer, pointer :: p => null()
+
+call sub2(%val(p)) ! Invalid: Nonassociated pointer
+end
+
+! Not quite correct dummy, but if one uses VALUE, gfortran
+! complains about a missing interface - which we cannot use
+! if we want to use %VAL().
+
+subroutine sub2(p)
+ integer :: p
+end subroutine sub2
diff --git a/gcc/testsuite/gfortran.dg/pointer_function_result_1.f90 b/gcc/testsuite/gfortran.dg/pointer_function_result_1.f90
new file mode 100644
index 00000000000..764a666be96
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_function_result_1.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! Test the fix for PR47844, in which the stride in the function result
+! was ignored. Previously, the result was [1,3] at lines 15 and 16.
+!
+! Contributed by KePu <Kdx1999@gmail.com>
+!
+PROGRAM test_pointer_value
+ IMPLICIT NONE
+ INTEGER, DIMENSION(10), TARGET :: array= [1,3,5,7,9,11,13,15,17,19]
+ INTEGER, dimension(2) :: array_fifth
+ INTEGER, POINTER, DIMENSION(:) :: ptr_array => NULL()
+ INTEGER, POINTER, DIMENSION(:) :: ptr_array_fifth => NULL()
+ ptr_array => array
+ array_fifth = every_fifth (ptr_array)
+ if (any (array_fifth .ne. [1,11])) call abort
+ if (any (every_fifth(ptr_array) .ne. [1,11])) call abort
+CONTAINS
+ FUNCTION every_fifth (ptr_array) RESULT (ptr_fifth)
+ IMPLICIT NONE
+ INTEGER, POINTER, DIMENSION(:) :: ptr_fifth
+ INTEGER, POINTER, DIMENSION(:), INTENT(in) :: ptr_array
+ INTEGER :: low
+ INTEGER :: high
+ low = LBOUND (ptr_array, 1)
+ high = UBOUND (ptr_array, 1)
+ ptr_fifth => ptr_array (low: high: 5)
+ END FUNCTION every_fifth
+END PROGRAM test_pointer_value
diff --git a/gcc/testsuite/gfortran.dg/pointer_intent_5.f90 b/gcc/testsuite/gfortran.dg/pointer_intent_5.f90
new file mode 100644
index 00000000000..c4e3c7a3c1d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_intent_5.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+!
+! PR 50570: [4.6/4.7 Regression] Incorrect error for assignment to intent(in) pointer
+!
+! Contributed by Bill Long <longb@cray.com>
+
+program bots_sparselu_pointer_intent_in
+
+ implicit none
+ integer, pointer :: array(:)
+
+ allocate(array(4))
+ array = 0
+ call sub(array)
+ if (sum(array)/=1) call abort
+
+contains
+
+ subroutine sub(dummy)
+ integer, pointer, intent(in) :: dummy(:)
+ dummy(1) = 1
+ end subroutine sub
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/proc_decl_27.f90 b/gcc/testsuite/gfortran.dg/proc_decl_27.f90
new file mode 100644
index 00000000000..30ff4def30d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_decl_27.f90
@@ -0,0 +1,25 @@
+! { dg-do compile }
+!
+! PR 50659: [4.5/4.6/4.7 Regression] [F03] ICE on invalid with procedure interface
+!
+! Contributed by Andrew Benson <abenson@caltech.edu>
+
+module m1
+ integer :: arrSize
+end module
+
+module m2
+contains
+ function Proc (arg)
+ use m1
+ double precision, dimension(arrSize) :: proc
+ double precision :: arg
+ end function
+end
+
+ use m2
+ implicit none
+ procedure(Proc) :: Proc_Get
+end
+
+! { dg-final { cleanup-modules "m1 m2" } }
diff --git a/gcc/testsuite/gfortran.dg/rank_3.f90 b/gcc/testsuite/gfortran.dg/rank_3.f90
index fac2185a9fe..c8f8fa77508 100644
--- a/gcc/testsuite/gfortran.dg/rank_3.f90
+++ b/gcc/testsuite/gfortran.dg/rank_3.f90
@@ -3,5 +3,5 @@
!
! PR fortran/48820
!
-intrinsic :: rank ! { dg-error "new in TR 29113" }
+intrinsic :: rank ! { dg-error "new in TS 29113" }
end
diff --git a/gcc/testsuite/gfortran.dg/rank_4.f90 b/gcc/testsuite/gfortran.dg/rank_4.f90
index 40b0209da95..a370df01c7d 100644
--- a/gcc/testsuite/gfortran.dg/rank_4.f90
+++ b/gcc/testsuite/gfortran.dg/rank_4.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-std=f2008tr -fdump-tree-original" }
+! { dg-options "-std=f2008ts -fdump-tree-original" }
!
! PR fortran/48820
!
diff --git a/gcc/testsuite/gfortran.dg/sizeof_proc.f90 b/gcc/testsuite/gfortran.dg/sizeof_proc.f90
new file mode 100644
index 00000000000..b4a2d732003
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/sizeof_proc.f90
@@ -0,0 +1,28 @@
+! { dg-do compile }
+!
+! PR 47023: C_Sizeof: Rejects valid code
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+use iso_c_binding
+procedure(real) :: proc
+procedure(real), pointer :: pp
+pp => sin
+
+print *,sizeof(proc) ! { dg-error "may not be a procedure" }
+print *,sizeof(pp) ! { dg-error "may not be a procedure" }
+print *,sizeof(pp(0.))
+print *,sizeof(sub) ! { dg-error "may not be a procedure" }
+print *,sizeof(func) ! { dg-error "may not be a procedure" }
+print *,sizeof(func())
+
+contains
+
+ subroutine sub
+ end subroutine
+
+ real function func()
+ func = 0.
+ end function
+
+end
diff --git a/gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f90 b/gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f90
new file mode 100644
index 00000000000..c31443f9468
--- /dev/null
+++ b/gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f90
@@ -0,0 +1,10 @@
+! Check for operand type validity after gimplification
+
+subroutine whatever()
+logical(kind=1) :: l1
+logical(kind=2) :: l2
+logical(kind=4) :: l3
+if ((l1 .and. l2) .neqv. l3) then
+ l1 = .true.
+endif
+end
diff --git a/gcc/testsuite/gnat.dg/specs/debug1.ads b/gcc/testsuite/gnat.dg/specs/debug1.ads
index ef7a86e3ddb..2fdc6e13e91 100644
--- a/gcc/testsuite/gnat.dg/specs/debug1.ads
+++ b/gcc/testsuite/gnat.dg/specs/debug1.ads
@@ -11,4 +11,4 @@ package Debug1 is
end Debug1;
--- { dg-final { scan-assembler-times "# DW_AT_artificial" 4 } }
+-- { dg-final { scan-assembler-times "DW_AT_artificial" 8 } }
diff --git a/gcc/testsuite/gnat.dg/vect1.adb b/gcc/testsuite/gnat.dg/vect1.adb
new file mode 100644
index 00000000000..0bbd9ee86a7
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect1.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect1 is
+
+ function "+" (X, Y : Varray) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Varray; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Sarray) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray1) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray2) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray3) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+end Vect1;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect1.ads b/gcc/testsuite/gnat.dg/vect1.ads
new file mode 100644
index 00000000000..48343fc0553
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect1.ads
@@ -0,0 +1,42 @@
+with Vect1_Pkg;
+
+package Vect1 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Integer range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X, Y : Varray) return Varray;
+ procedure Add (X, Y : not null access Varray; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (1 .. 4) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X, Y : Sarray) return Sarray;
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray);
+
+
+ type Darray1 is array (1 .. Vect1_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X, Y : Darray1) return Darray1;
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect1_Pkg.K .. 4) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X, Y : Darray2) return Darray2;
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect1_Pkg.K .. Vect1_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X, Y : Darray3) return Darray3;
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3);
+
+end Vect1;
diff --git a/gcc/testsuite/gnat.dg/vect1_pkg.ads b/gcc/testsuite/gnat.dg/vect1_pkg.ads
new file mode 100644
index 00000000000..b9fab52b1e2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect1_pkg.ads
@@ -0,0 +1,6 @@
+package Vect1_Pkg is
+
+ function K return Integer;
+ function N return Integer;
+
+end Vect1_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect2.adb b/gcc/testsuite/gnat.dg/vect2.adb
new file mode 100644
index 00000000000..54e0403f135
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect2.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect2 is
+
+ function "+" (X, Y : Varray) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Varray; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Sarray) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray1) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray2) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray3) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+end Vect2;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect2.ads b/gcc/testsuite/gnat.dg/vect2.ads
new file mode 100644
index 00000000000..b5111875924
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect2.ads
@@ -0,0 +1,42 @@
+with Vect2_Pkg;
+
+package Vect2 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Positive range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X, Y : Varray) return Varray;
+ procedure Add (X, Y : not null access Varray; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Positive(1) .. Positive(4)) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X, Y : Sarray) return Sarray;
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray);
+
+
+ type Darray1 is array (Positive(1) .. Vect2_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X, Y : Darray1) return Darray1;
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect2_Pkg.K .. Positive(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X, Y : Darray2) return Darray2;
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect2_Pkg.K .. Vect2_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X, Y : Darray3) return Darray3;
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3);
+
+end Vect2;
diff --git a/gcc/testsuite/gnat.dg/vect2_pkg.ads b/gcc/testsuite/gnat.dg/vect2_pkg.ads
new file mode 100644
index 00000000000..804e10caebc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect2_pkg.ads
@@ -0,0 +1,6 @@
+package Vect2_Pkg is
+
+ function K return Positive;
+ function N return Positive;
+
+end Vect2_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect3.adb b/gcc/testsuite/gnat.dg/vect3.adb
new file mode 100644
index 00000000000..3baa6388e17
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect3.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect3 is
+
+ function "+" (X, Y : Varray) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Varray; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Sarray) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray1) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray2) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray3) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+end Vect3;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect3.ads b/gcc/testsuite/gnat.dg/vect3.ads
new file mode 100644
index 00000000000..d78e3c44cff
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect3.ads
@@ -0,0 +1,43 @@
+with Vect3_Pkg;
+
+package Vect3 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Vect3_Pkg.Index_Type range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X, Y : Varray) return Varray;
+ procedure Add (X, Y : not null access Varray; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Vect3_Pkg.Index_Type(1) .. Vect3_Pkg.Index_Type(4))
+ of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X, Y : Sarray) return Sarray;
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray);
+
+
+ type Darray1 is array (Vect3_Pkg.Index_Type(1) .. Vect3_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X, Y : Darray1) return Darray1;
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect3_Pkg.K .. Vect3_Pkg.Index_Type(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X, Y : Darray2) return Darray2;
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect3_Pkg.K .. Vect3_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X, Y : Darray3) return Darray3;
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3);
+
+end Vect3;
diff --git a/gcc/testsuite/gnat.dg/vect3_pkg.ads b/gcc/testsuite/gnat.dg/vect3_pkg.ads
new file mode 100644
index 00000000000..8c926bbcd6a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect3_pkg.ads
@@ -0,0 +1,10 @@
+with System;
+
+package Vect3_Pkg is
+
+ type Index_Type is mod System.Memory_Size;
+
+ function K return Index_Type;
+ function N return Index_Type;
+
+end Vect3_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect4.adb b/gcc/testsuite/gnat.dg/vect4.adb
new file mode 100644
index 00000000000..032a7289394
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect4.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect4 is
+
+ function "+" (X : Varray; Y : Long_Float) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+end Vect4;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect4.ads b/gcc/testsuite/gnat.dg/vect4.ads
new file mode 100644
index 00000000000..98df7efeebc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect4.ads
@@ -0,0 +1,42 @@
+with Vect4_Pkg;
+
+package Vect4 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Integer range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X : Varray; Y : Long_Float) return Varray;
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (1 .. 4) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray;
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray);
+
+
+ type Darray1 is array (1 .. Vect4_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1;
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect4_Pkg.K .. 4) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2;
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect4_Pkg.K .. Vect4_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3;
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3);
+
+end Vect4;
diff --git a/gcc/testsuite/gnat.dg/vect4_pkg.ads b/gcc/testsuite/gnat.dg/vect4_pkg.ads
new file mode 100644
index 00000000000..2e0008d0a71
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect4_pkg.ads
@@ -0,0 +1,6 @@
+package Vect4_Pkg is
+
+ function K return Integer;
+ function N return Integer;
+
+end Vect4_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect5.adb b/gcc/testsuite/gnat.dg/vect5.adb
new file mode 100644
index 00000000000..98af2c01d54
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect5.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect5 is
+
+ function "+" (X : Varray; Y : Long_Float) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+end Vect5;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect5.ads b/gcc/testsuite/gnat.dg/vect5.ads
new file mode 100644
index 00000000000..09e798aecb2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect5.ads
@@ -0,0 +1,42 @@
+with Vect5_Pkg;
+
+package Vect5 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Positive range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X : Varray; Y : Long_Float) return Varray;
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Positive (1) .. Positive (4)) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray;
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray);
+
+
+ type Darray1 is array (Positive(1) .. Vect5_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1;
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect5_Pkg.K .. Positive(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2;
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect5_Pkg.K .. Vect5_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3;
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3);
+
+end Vect5;
diff --git a/gcc/testsuite/gnat.dg/vect5_pkg.ads b/gcc/testsuite/gnat.dg/vect5_pkg.ads
new file mode 100644
index 00000000000..9eb752eedb2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect5_pkg.ads
@@ -0,0 +1,6 @@
+package Vect5_Pkg is
+
+ function K return Positive;
+ function N return Positive;
+
+end Vect5_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect6.adb b/gcc/testsuite/gnat.dg/vect6.adb
new file mode 100644
index 00000000000..425f2a70362
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect6.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect6 is
+
+ function "+" (X : Varray; Y : Long_Float) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+end Vect6;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect6.ads b/gcc/testsuite/gnat.dg/vect6.ads
new file mode 100644
index 00000000000..013fe13652e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect6.ads
@@ -0,0 +1,43 @@
+with Vect6_Pkg;
+
+package Vect6 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Vect6_Pkg.Index_Type range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X : Varray; Y : Long_Float) return Varray;
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Vect6_Pkg.Index_Type(1) .. Vect6_Pkg.Index_Type(4))
+ of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray;
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray);
+
+
+ type Darray1 is array (Vect6_Pkg.Index_Type(1) .. Vect6_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1;
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect6_Pkg.K .. Vect6_Pkg.Index_Type(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2;
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect6_Pkg.K .. Vect6_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3;
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3);
+
+end Vect6;
diff --git a/gcc/testsuite/gnat.dg/vect6_pkg.ads b/gcc/testsuite/gnat.dg/vect6_pkg.ads
new file mode 100644
index 00000000000..7db734a359f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect6_pkg.ads
@@ -0,0 +1,10 @@
+with System;
+
+package Vect6_Pkg is
+
+ type Index_Type is mod System.Memory_Size;
+
+ function K return Index_Type;
+ function N return Index_Type;
+
+end Vect6_Pkg;
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 9ce0149fddb..6bac368d43d 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -747,4 +747,26 @@ proc dg-message { args } {
process-message saved-dg-warning "" $args
}
+# Check the existence of a gdb in the path, and return true if there
+# is one.
+#
+# Set env(GDB_FOR_GCC_TESTING) accordingly.
+
+proc gdb-exists { args } {
+ if ![info exists ::env(GDB_FOR_GCC_TESTING)] {
+ global GDB
+ if ![info exists ::env(GDB_FOR_GCC_TESTING)] {
+ if [info exists GDB] {
+ setenv GDB_FOR_GCC_TESTING "$GDB"
+ } else {
+ setenv GDB_FOR_GCC_TESTING "[transform gdb]"
+ }
+ }
+ }
+ if { [which $::env(GDB_FOR_GCC_TESTING)] != 0 } {
+ return 1;
+ }
+ return 0;
+}
+
set additional_prunes ""
diff --git a/gcc/testsuite/lib/gcc-gdb-test.exp b/gcc/testsuite/lib/gcc-gdb-test.exp
index 22e7a491873..2f593ab2edf 100644
--- a/gcc/testsuite/lib/gcc-gdb-test.exp
+++ b/gcc/testsuite/lib/gcc-gdb-test.exp
@@ -56,6 +56,7 @@ proc gdb-test { args } {
set res [remote_spawn target "$gdb_name -nx -nw -quiet -x $cmd_file ./$output_file"]
if { $res < 0 || $res == "" } {
unsupported "$testname"
+ file delete $cmd_file
return
}
@@ -64,6 +65,7 @@ proc gdb-test { args } {
-re "Unhandled dwarf expression|Error in sourced command file" {
unsupported "$testname"
remote_close target
+ file delete $cmd_file
return
}
-re {[\n\r]\$1 = ([^\n\r]*)[\n\r]+\$2 = ([^\n\r]*)[\n\r]} {
@@ -76,16 +78,19 @@ proc gdb-test { args } {
fail "$testname"
}
remote_close target
+ file delete $cmd_file
return
}
timeout {
unsupported "$testname"
remote_close target
+ file delete $cmd_file
return
}
}
- remote_close target
unsupported "$testname"
+ remote_close target
+ file delete $cmd_file
return
}
diff --git a/gcc/testsuite/lib/gcc-simulate-thread.exp b/gcc/testsuite/lib/gcc-simulate-thread.exp
new file mode 100644
index 00000000000..ba2416acdd7
--- /dev/null
+++ b/gcc/testsuite/lib/gcc-simulate-thread.exp
@@ -0,0 +1,90 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Utility for running a given test through the simulate-thread harness
+# using gdb. This is invoked via dg-final.
+#
+# Adapted from the guality harness.
+#
+# Call 'fail' if a given test printed "FAIL:", otherwise call 'pass'.
+
+proc simulate-thread { args } {
+ if { ![isnative] || [is_remote target] } { return }
+
+ if { [llength $args] == 1 } {
+ switch [dg-process-target [lindex $args 0]] {
+ "F" { setup_xfail "*-*-*" }
+ }
+ }
+
+ # This assumes that we are three frames down from dg-test, and that
+ # it still stores the filename of the testcase in a local variable "name".
+ # A cleaner solution would require a new DejaGnu release.
+ upvar 2 name testcase
+ upvar 2 prog prog
+ upvar 2 srcdir testsuite_dir
+
+ set gdb_name $::env(GDB_FOR_GCC_TESTING)
+ set exec_file "[file rootname [file tail $prog]].exe"
+ set cmd_file "$testsuite_dir/gcc.dg/simulate-thread/simulate-thread.gdb"
+
+ if ![file exists $exec_file] {
+ return
+ }
+
+ send_log "Spawning: $gdb_name -nx -nw -quiet -x $cmd_file ./$exec_file\n"
+ set res [remote_spawn target "$gdb_name -nx -nw -x $cmd_file ./$exec_file"]
+ if { $res < 0 || $res == "" } {
+ unsupported "$testcase"
+ return
+ }
+
+ set gdb_worked 0
+ remote_expect target [timeout_value] {
+ # Too old GDB
+ -re "Unhandled dwarf expression|Error in sourced command file" {
+ unsupported "$testcase"
+ remote_close target
+ return
+ }
+ -re "FAIL:" {
+ fail "$testcase"
+ remote_close target
+ return
+ }
+ # If the gdb output contained simulate_thread_main, assume
+ # that at the very least, we had a working gdb that was able
+ # to break in simulate_thread_main.
+ -re "simulate_thread_main" {
+ set gdb_worked 1
+ exp_continue
+ }
+ timeout {
+ unsupported "$testcase"
+ remote_close target
+ return
+ }
+ }
+
+ remote_close target
+ if {$gdb_worked} {
+ pass "$testcase"
+ } else {
+ # Fail in the absence of a sane GDB.
+ fail "$testcase"
+ }
+ return
+}
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 4683f931589..09d25811106 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -29,6 +29,7 @@ proc prune_gcc_output { text } {
regsub -all "(^|\n)collect: re(compiling|linking)\[^\n\]*" $text "" text
regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text
regsub -all "(^|\n)\[0-9\]\[0-9\]* errors\." $text "" text
+ regsub -all "(^|\n)(In file included|\[ \]+from)\[^\n\]*" $text "" text
# Ignore informational notes.
regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index accaad518ef..f19c3c566c6 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1973,6 +1973,18 @@ proc check_effective_target_arm_dsp { } {
}]
}
+# Return 1 if this is an ARM target that supports unaligned word/halfword
+# load/store instructions.
+
+proc check_effective_target_arm_unaligned { } {
+ return [check_no_compiler_messages arm_unaligned assembly {
+ #ifndef __ARM_FEATURE_UNALIGNED
+ #error no unaligned support
+ #endif
+ int i;
+ }]
+}
+
# Add the options needed for NEON. We need either -mfloat-abi=softfp
# or -mfloat-abi=hard, but if one is already specified by the
# multilib, use it. Similarly, if a -mfpu option already enables
@@ -2067,6 +2079,47 @@ proc check_effective_target_arm_fp16_ok { } {
check_effective_target_arm_fp16_ok_nocache]
}
+# Creates a series of routines that return 1 if the given architecture
+# can be selected and a routine to give the flags to select that architecture
+# Note: Extra flags may be added to disable options from newer compilers
+# (Thumb in particular - but others may be added in the future)
+# Usage: /* { dg-require-effective-target arm_arch_v5_ok } */
+# /* { dg-add-options arm_arch_v5 } */
+foreach { armfunc armflag armdef } { v5 "-march=armv5 -marm" __ARM_ARCH_5__
+ v6 "-march=armv6" __ARM_ARCH_6__
+ v6k "-march=armv6k" __ARM_ARCH_6K__
+ v7a "-march=armv7-a" __ARM_ARCH_7A__ } {
+ eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] {
+ proc check_effective_target_arm_arch_FUNC_ok { } {
+ if { [ string match "*-marm*" "FLAG" ] &&
+ ![check_effective_target_arm_arm_ok] } {
+ return 0
+ }
+ return [check_no_compiler_messages arm_arch_FUNC_ok assembly {
+ #if !defined (DEF)
+ #error FOO
+ #endif
+ } "FLAG" ]
+ }
+
+ proc add_options_for_arm_arch_FUNC { flags } {
+ return "$flags FLAG"
+ }
+ }]
+}
+
+# Return 1 if this is an ARM target where -marm causes ARM to be
+# used (not Thumb)
+
+proc check_effective_target_arm_arm_ok { } {
+ return [check_no_compiler_messages arm_arm_ok assembly {
+ #if !defined (__arm__) || defined (__thumb__) || defined (__thumb2__)
+ #error FOO
+ #endif
+ } "-marm"]
+}
+
+
# Return 1 is this is an ARM target where -mthumb causes Thumb-1 to be
# used.
@@ -2421,27 +2474,6 @@ proc check_effective_target_vect_shift { } {
return $et_vect_shift_saved
}
-# Return 1 if the target supports hardware vector shift operation with
-# scalar shift argument.
-
-proc check_effective_target_vect_shift_scalar { } {
- global et_vect_shift_scalar_saved
-
- if [info exists et_vect_shift_scalar_saved] {
- verbose "check_effective_target_vect_shift_scalar: using cached result" 2
- } else {
- set et_vect_shift_scalar_saved 0
- if { [istarget x86_64-*-*]
- || [istarget i?86-*-*] } {
- set et_vect_shift_scalar_saved 1
- }
- }
-
- verbose "check_effective_target_vect_shift_scalar: returning $et_vect_shift_scalar_saved" 2
- return $et_vect_shift_scalar_saved
-}
-
-
# Return 1 if the target supports hardware vector shift operation for char.
proc check_effective_target_vect_shift_char { } {
@@ -2887,6 +2919,26 @@ proc check_effective_target_vect_widen_mult_hi_to_si_pattern { } {
}
# Return 1 if the target plus current options supports a vector
+# widening shift, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_widen_shift { } {
+ global et_vect_widen_shift_saved
+
+ if [info exists et_vect_shift_saved] {
+ verbose "check_effective_target_vect_widen_shift: using cached result" 2
+ } else {
+ set et_vect_widen_shift_saved 0
+ if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } {
+ set et_vect_widen_shift_saved 1
+ }
+ }
+ verbose "check_effective_target_vect_widen_shift: returning $et_vect_widen_shift_saved" 2
+ return $et_vect_widen_shift_saved
+}
+
+# Return 1 if the target plus current options supports a vector
# dot-product of signed chars, 0 otherwise.
#
# This won't change for different subtargets so cache the result.
@@ -3234,6 +3286,26 @@ proc check_effective_target_vect_condition { } {
return $et_vect_cond_saved
}
+# Return 1 if the target supports vector conditional operations where
+# the comparison has different type from the lhs, 0 otherwise.
+
+proc check_effective_target_vect_cond_mixed { } {
+ global et_vect_cond_mixed_saved
+
+ if [info exists et_vect_cond_mixed_saved] {
+ verbose "check_effective_target_vect_cond_mixed: using cached result" 2
+ } else {
+ set et_vect_cond_mixed_saved 0
+ if { [istarget i?86-*-*]
+ || [istarget x86_64-*-*] } {
+ set et_vect_cond_mixed_saved 1
+ }
+ }
+
+ verbose "check_effective_target_vect_cond_mixed: returning $et_vect_cond_mixed_saved" 2
+ return $et_vect_cond_mixed_saved
+}
+
# Return 1 if the target supports vector char multiplication, 0 otherwise.
proc check_effective_target_vect_char_mult { } {
@@ -3375,7 +3447,7 @@ foreach N {2 3 4 8} {
# Return 1 if the target supports multiple vector sizes
proc check_effective_target_vect_multiple_sizes { } {
- global et_vect_multiple_sizes
+ global et_vect_multiple_sizes_saved
if [info exists et_vect_multiple_sizes_saved] {
verbose "check_effective_target_vect_multiple_sizes: using cached result" 2
@@ -3393,7 +3465,7 @@ proc check_effective_target_vect_multiple_sizes { } {
# Return 1 if the target supports vectors of 64 bits.
proc check_effective_target_vect64 { } {
- global et_vect64
+ global et_vect64_saved
if [info exists et_vect64_saved] {
verbose "check_effective_target_vect64: using cached result" 2
@@ -3458,6 +3530,31 @@ proc check_effective_target_sync_int_long { } {
return $et_sync_int_long_saved
}
+# Return 1 if the target supports atomic operations on "long long" and can
+# execute them
+# So far only put checks in for ARM, others may want to add their own
+proc check_effective_target_sync_longlong { } {
+ return [check_runtime sync_longlong_runtime {
+ #include <stdlib.h>
+ int main ()
+ {
+ long long l1;
+
+ if (sizeof (long long) != 8)
+ exit (1);
+
+ #ifdef __arm__
+ /* Just check for native; checking for kernel fallback is tricky. */
+ asm volatile ("ldrexd r0,r1, [%0]" : : "r" (&l1) : "r0", "r1");
+ #else
+ # error "Add other suitable archs here"
+ #endif
+
+ exit (0);
+ }
+ } "" ]
+}
+
# Return 1 if the target supports atomic operations on "char" and "short".
proc check_effective_target_sync_char_short { } {
@@ -3719,16 +3816,25 @@ proc check_effective_target_fd_truncate { } {
int fd;
const char t[] = "test writing more than ten characters";
char s[11];
- fd = fileno (f);
+ int status = 0;
+ fd = fileno (f);
write (fd, t, sizeof (t) - 1);
lseek (fd, 0, 0);
if (ftruncate (fd, 10) != 0)
- exit (1);
+ status = 1;
close (fd);
+ fclose (f);
+ if (status)
+ {
+ unlink ("tst.tmp");
+ exit (status);
+ }
f = fopen ("tst.tmp", "rb");
if (fread (s, 1, sizeof (s), f) != 10 || strncmp (s, t, 10) != 0)
- exit (1);
- exit (0);
+ status = 1;
+ fclose (f);
+ unlink ("tst.tmp");
+ exit (status);
}
}
diff --git a/gcc/testsuite/obj-c++.dg/warn6.mm b/gcc/testsuite/obj-c++.dg/warn6.mm
new file mode 100644
index 00000000000..a74f8025d0e
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/warn6.mm
@@ -0,0 +1,7 @@
+// PR c++/17212
+// { dg-options "-Wformat -Wno-format-zero-length" }
+
+void f()
+{
+ __builtin_printf("");
+}
diff --git a/gcc/testsuite/obj-c++.dg/warn7.mm b/gcc/testsuite/obj-c++.dg/warn7.mm
new file mode 100644
index 00000000000..6e84069eec5
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/warn7.mm
@@ -0,0 +1,10 @@
+// PR c++/50757
+// { dg-options "-Wformat -Wno-nonnull" }
+
+extern void *f (void *__s) __attribute__ ((__nonnull__ (1)));
+
+int main()
+{
+ void* const s = 0;
+ f(s);
+}
diff --git a/gcc/testsuite/objc/execute/initialize-1.m b/gcc/testsuite/objc/execute/initialize-1.m
new file mode 100644
index 00000000000..9ca4aebbe69
--- /dev/null
+++ b/gcc/testsuite/objc/execute/initialize-1.m
@@ -0,0 +1,47 @@
+/* Contributed by Nicola Pero - Sat 8 Oct 2011 16:47:48 BST */
+#include <objc/objc.h>
+
+/* Test that if a class has no +initialize method, the superclass
+ implementation is called. */
+
+static int class_variable = 0;
+
+@interface TestClass
+{
+ Class isa;
+}
++ (void) initialize;
++ (int) classVariable;
+@end
+
+@implementation TestClass
++ (void) initialize
+{
+ class_variable++;
+}
++ (int) classVariable
+{
+ return class_variable;
+}
+@end
+
+@interface TestSubClass : TestClass
+@end
+
+@implementation TestSubClass
+@end
+
+int main (void)
+{
+ if ([TestClass classVariable] != 1)
+ {
+ abort ();
+ }
+
+ if ([TestSubClass classVariable] != 2)
+ {
+ abort ();
+ }
+
+ return 0;
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index ab6b5a41837..86eed5d63a8 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -651,13 +651,13 @@ compile_file (void)
{
#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE,
- "__gnu_slim_lto",
+ "__gnu_lto_slim",
(unsigned HOST_WIDE_INT) 1, 8);
#elif defined ASM_OUTPUT_ALIGNED_COMMON
- ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_slim_lto",
+ ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_slim",
(unsigned HOST_WIDE_INT) 1, 8);
#else
- ASM_OUTPUT_COMMON (asm_out_file, "__gnu_slim_lto",
+ ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_slim",
(unsigned HOST_WIDE_INT) 1,
(unsigned HOST_WIDE_INT) 1);
#endif
@@ -1171,6 +1171,9 @@ general_init (const char *argv0)
can give warnings and errors. */
diagnostic_initialize (global_dc, N_OPTS);
diagnostic_starter (global_dc) = default_tree_diagnostic_starter;
+ /* By default print macro expansion contexts in the diagnostic
+ finalizer -- for tokens resulting from macro macro expansion. */
+ diagnostic_finalizer (global_dc) = virt_loc_aware_diagnostic_finalizer;
/* Set a default printer. Language specific initializations will
override it later. */
pp_format_decoder (global_dc->printer) = &default_tree_printer;
@@ -1213,6 +1216,7 @@ general_init (const char *argv0)
line_table = ggc_alloc_line_maps ();
linemap_init (line_table);
line_table->reallocator = realloc_for_line_map;
+ line_table->round_alloc_size = ggc_round_alloc_size;
init_ttree ();
/* Initialize register usage now so switches may override. */
@@ -1824,6 +1828,7 @@ target_reinit (void)
void
dump_memory_report (bool final)
{
+ dump_line_table_statistics ();
ggc_print_statistics ();
stringpool_statistics ();
dump_tree_statistics ();
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 5e5de8f372b..a8409db5982 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3510,6 +3510,44 @@ verify_gimple_assign_binary (gimple stmt)
return false;
}
+ case WIDEN_LSHIFT_EXPR:
+ {
+ if (!INTEGRAL_TYPE_P (lhs_type)
+ || !INTEGRAL_TYPE_P (rhs1_type)
+ || TREE_CODE (rhs2) != INTEGER_CST
+ || (2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)))
+ {
+ error ("type mismatch in widening vector shift expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ return true;
+ }
+
+ return false;
+ }
+
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ {
+ if (TREE_CODE (rhs1_type) != VECTOR_TYPE
+ || TREE_CODE (lhs_type) != VECTOR_TYPE
+ || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
+ || !INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))
+ || TREE_CODE (rhs2) != INTEGER_CST
+ || (2 * TYPE_PRECISION (TREE_TYPE (rhs1_type))
+ > TYPE_PRECISION (TREE_TYPE (lhs_type))))
+ {
+ error ("type mismatch in widening vector shift expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ return true;
+ }
+
+ return false;
+ }
+
case PLUS_EXPR:
case MINUS_EXPR:
{
@@ -3727,6 +3765,59 @@ verify_gimple_assign_ternary (gimple stmt)
}
break;
+ case VEC_PERM_EXPR:
+ if (!useless_type_conversion_p (lhs_type, rhs1_type)
+ || !useless_type_conversion_p (lhs_type, rhs2_type))
+ {
+ error ("type mismatch in vector permute expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ if (TREE_CODE (rhs1_type) != VECTOR_TYPE
+ || TREE_CODE (rhs2_type) != VECTOR_TYPE
+ || TREE_CODE (rhs3_type) != VECTOR_TYPE)
+ {
+ error ("vector types expected in vector permute expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ if (TYPE_VECTOR_SUBPARTS (rhs1_type) != TYPE_VECTOR_SUBPARTS (rhs2_type)
+ || TYPE_VECTOR_SUBPARTS (rhs2_type)
+ != TYPE_VECTOR_SUBPARTS (rhs3_type)
+ || TYPE_VECTOR_SUBPARTS (rhs3_type)
+ != TYPE_VECTOR_SUBPARTS (lhs_type))
+ {
+ error ("vectors with different element number found "
+ "in vector permute expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ if (TREE_CODE (TREE_TYPE (rhs3_type)) != INTEGER_TYPE
+ || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs3_type)))
+ != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type))))
+ {
+ error ("invalid mask type in vector permute expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ debug_generic_expr (rhs3_type);
+ return true;
+ }
+
+ return false;
+
case DOT_PROD_EXPR:
case REALIGN_LOAD_EXPR:
/* FIXME. */
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 1b2a588ee2e..0547fcf147f 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -956,7 +956,7 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai,
(BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
else
gcc_unreachable ();
- fn = built_in_decls[bcode];
+ fn = builtin_decl_explicit (bcode);
stmt = gimple_build_call (fn, 4, ar, ai, br, bi);
gimple_call_set_lhs (stmt, lhs);
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index a4c9367d9c6..053ffea1303 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -589,9 +589,6 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
int punsignedp, pvolatilep;
op0 = TREE_OPERAND (op0, 0);
- if (!handled_component_p (op0))
- return false;
-
base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset,
&pmode, &punsignedp, &pvolatilep, false);
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 62d4bfe3fb8..0ecec816b6a 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -580,8 +580,9 @@ set_default_def (tree var, tree def)
bool
add_referenced_var (tree var)
{
- get_var_ann (var);
gcc_assert (DECL_P (var));
+ if (!*DECL_VAR_ANN_PTR (var))
+ create_var_ann (var);
/* Insert VAR into the referenced_vars hash table if it isn't present. */
if (referenced_var_check_and_insert (var))
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index b456a2a5fbf..53b350b5418 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-diagnostic.h"
#include "langhooks.h"
#include "langhooks-def.h"
+#include "vec.h"
/* Prints out, if necessary, the name of the current function
that caused an error. Called from all error and warning functions. */
@@ -35,7 +36,7 @@ void
diagnostic_report_current_function (diagnostic_context *context,
diagnostic_info *diagnostic)
{
- diagnostic_report_current_module (context);
+ diagnostic_report_current_module (context, diagnostic->location);
lang_hooks.print_error_function (context, input_filename, diagnostic);
}
@@ -47,3 +48,182 @@ default_tree_diagnostic_starter (diagnostic_context *context,
pp_set_prefix (context->printer, diagnostic_build_prefix (context,
diagnostic));
}
+
+/* This is a pair made of a location and the line map it originated
+ from. It's used in the maybe_unwind_expanded_macro_loc function
+ below. */
+typedef struct
+{
+ const struct line_map *map;
+ source_location where;
+} loc_t;
+
+DEF_VEC_O (loc_t);
+DEF_VEC_ALLOC_O (loc_t, heap);
+
+/* Unwind the different macro expansions that lead to the token which
+ location is WHERE and emit diagnostics showing the resulting
+ unwound macro expansion trace. Let's look at an example to see how
+ the trace looks like. Suppose we have this piece of code,
+ artificially annotated with the line numbers to increase
+ legibility:
+
+ $ cat -n test.c
+ 1 #define OPERATE(OPRD1, OPRT, OPRD2) \
+ 2 OPRD1 OPRT OPRD2;
+ 3
+ 4 #define SHIFTL(A,B) \
+ 5 OPERATE (A,<<,B)
+ 6
+ 7 #define MULT(A) \
+ 8 SHIFTL (A,1)
+ 9
+ 10 void
+ 11 g ()
+ 12 {
+ 13 MULT (1.0);// 1.0 << 1; <-- so this is an error.
+ 14 }
+
+ Here is the diagnostic that we want the compiler to generate:
+
+ test.c: In function 'g':
+ test.c:5:14: error: invalid operands to binary << (have 'double' and 'int')
+ test.c:2:9: note: in expansion of macro 'OPERATE'
+ test.c:5:3: note: expanded from here
+ test.c:5:14: note: in expansion of macro 'SHIFTL'
+ test.c:8:3: note: expanded from here
+ test.c:8:3: note: in expansion of macro 'MULT2'
+ test.c:13:3: note: expanded from here
+
+ The part that goes from the third to the eighth line of this
+ diagnostic (the lines containing the 'note:' string) is called the
+ unwound macro expansion trace. That's the part generated by this
+ function.
+
+ If FIRST_EXP_POINT_MAP is non-null, *FIRST_EXP_POINT_MAP is set to
+ the map of the location in the source that first triggered the
+ macro expansion. This must be an ordinary map. */
+
+static void
+maybe_unwind_expanded_macro_loc (diagnostic_context *context,
+ diagnostic_info *diagnostic,
+ source_location where,
+ const struct line_map **first_exp_point_map)
+{
+ const struct line_map *map;
+ VEC(loc_t,heap) *loc_vec = NULL;
+ unsigned ix;
+ loc_t loc, *iter;
+
+ map = linemap_lookup (line_table, where);
+ if (!linemap_macro_expansion_map_p (map))
+ return;
+
+ /* Let's unwind the macros that got expanded and led to the token
+ which location is WHERE. We are going to store these macros into
+ LOC_VEC, so that we can later walk it at our convenience to
+ display a somewhat meaningful trace of the macro expansion
+ history to the user. Note that the first macro of the trace
+ (which is OPERATE in the example above) is going to be stored at
+ the beginning of LOC_VEC. */
+
+ do
+ {
+ loc.where = where;
+ loc.map = map;
+
+ VEC_safe_push (loc_t, heap, loc_vec, &loc);
+
+ /* WHERE is the location of a token inside the expansion of a
+ macro. MAP is the map holding the locations of that macro
+ expansion. Let's get the location of the token inside the
+ context that triggered the expansion of this macro.
+ This is basically how we go "down" in the trace of macro
+ expansions that led to WHERE. */
+ where = linemap_unwind_toward_expansion (line_table, where, &map);
+ } while (linemap_macro_expansion_map_p (map));
+
+ if (first_exp_point_map)
+ *first_exp_point_map = map;
+
+ /* Walk LOC_VEC and print the macro expansion trace, unless the
+ first macro which expansion triggered this trace was expanded
+ inside a system header. */
+ if (!LINEMAP_SYSP (map))
+ FOR_EACH_VEC_ELT (loc_t, loc_vec, ix, iter)
+ {
+ source_location resolved_def_loc = 0, resolved_exp_loc = 0;
+ diagnostic_t saved_kind;
+ const char *saved_prefix;
+ source_location saved_location;
+
+ /* Okay, now here is what we want. For each token resulting
+ from macro expansion we want to show: 1/ where in the
+ definition of the macro the token comes from; 2/ where the
+ macro got expanded. */
+
+ /* Resolve the location iter->where into the locus 1/ of the
+ comment above. */
+ resolved_def_loc =
+ linemap_resolve_location (line_table, iter->where,
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+
+ /* Resolve the location of the expansion point of the macro
+ which expansion gave the token represented by def_loc.
+ This is the locus 2/ of the earlier comment. */
+ resolved_exp_loc =
+ linemap_resolve_location (line_table,
+ MACRO_MAP_EXPANSION_POINT_LOCATION (iter->map),
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+
+ saved_kind = diagnostic->kind;
+ saved_prefix = context->printer->prefix;
+ saved_location = diagnostic->location;
+
+ diagnostic->kind = DK_NOTE;
+ diagnostic->location = resolved_def_loc;
+ pp_base_set_prefix (context->printer,
+ diagnostic_build_prefix (context,
+ diagnostic));
+ pp_newline (context->printer);
+ pp_printf (context->printer, "in expansion of macro '%s'",
+ linemap_map_get_macro_name (iter->map));
+ pp_destroy_prefix (context->printer);
+
+ diagnostic->location = resolved_exp_loc;
+ pp_base_set_prefix (context->printer,
+ diagnostic_build_prefix (context,
+ diagnostic));
+ pp_newline (context->printer);
+ pp_printf (context->printer, "expanded from here");
+ pp_destroy_prefix (context->printer);
+
+ diagnostic->kind = saved_kind;
+ diagnostic->location = saved_location;
+ context->printer->prefix = saved_prefix;
+ }
+
+ VEC_free (loc_t, heap, loc_vec);
+}
+
+/* This is a diagnostic finalizer implementation that is aware of
+ virtual locations produced by libcpp.
+
+ It has to be called by the diagnostic finalizer of front ends that
+ uses libcpp and wish to get diagnostics involving tokens resulting
+ from macro expansion.
+
+ For a given location, if said location belongs to a token
+ resulting from a macro expansion, this starter prints the context
+ of the token. E.g, for multiply nested macro expansion, it
+ unwinds the nested macro expansions and prints them in a manner
+ that is similar to what is done for function call stacks, or
+ template instantiation contexts. */
+void
+virt_loc_aware_diagnostic_finalizer (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ maybe_unwind_expanded_macro_loc (context, diagnostic,
+ diagnostic->location,
+ NULL);
+}
diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h
index 7d88089069f..6b8e8e6e437 100644
--- a/gcc/tree-diagnostic.h
+++ b/gcc/tree-diagnostic.h
@@ -52,5 +52,6 @@ along with GCC; see the file COPYING3. If not see
void default_tree_diagnostic_starter (diagnostic_context *, diagnostic_info *);
extern void diagnostic_report_current_function (diagnostic_context *,
diagnostic_info *);
-
+void virt_loc_aware_diagnostic_finalizer (diagnostic_context *,
+ diagnostic_info *);
#endif /* ! GCC_TREE_DIAGNOSTIC_H */
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 3a582678f33..c1896be228d 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2512,7 +2512,13 @@ stmt_could_throw_1_p (gimple stmt)
|| TREE_CODE_CLASS (code) == tcc_unary
|| TREE_CODE_CLASS (code) == tcc_binary)
{
- t = gimple_expr_type (stmt);
+ if (is_gimple_assign (stmt)
+ && TREE_CODE_CLASS (code) == tcc_comparison)
+ t = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ else if (gimple_code (stmt) == GIMPLE_COND)
+ t = TREE_TYPE (gimple_cond_lhs (stmt));
+ else
+ t = gimple_expr_type (stmt);
fp_operation = FLOAT_TYPE_P (t);
if (fp_operation)
{
@@ -2934,7 +2940,7 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
Resolve this by expanding the resx node to an abort. */
- fn = implicit_built_in_decls[BUILT_IN_TRAP];
+ fn = builtin_decl_implicit (BUILT_IN_TRAP);
x = gimple_build_call (fn, 0);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
@@ -2991,7 +2997,7 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
edge_iterator ei;
tree dst_nr = build_int_cst (integer_type_node, dst_r->index);
- fn = implicit_built_in_decls[BUILT_IN_EH_COPY_VALUES];
+ fn = builtin_decl_implicit (BUILT_IN_EH_COPY_VALUES);
src_nr = build_int_cst (integer_type_node, src_r->index);
x = gimple_build_call (fn, 2, dst_nr, src_nr);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
@@ -3026,13 +3032,13 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
with no arguments for C++ and Java. Check for that. */
if (src_r->use_cxa_end_cleanup)
{
- fn = implicit_built_in_decls[BUILT_IN_CXA_END_CLEANUP];
+ fn = builtin_decl_implicit (BUILT_IN_CXA_END_CLEANUP);
x = gimple_build_call (fn, 0);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
}
else
{
- fn = implicit_built_in_decls[BUILT_IN_EH_POINTER];
+ fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
src_nr = build_int_cst (integer_type_node, src_r->index);
x = gimple_build_call (fn, 1, src_nr);
var = create_tmp_var (ptr_type_node, NULL);
@@ -3040,7 +3046,7 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
gimple_call_set_lhs (x, var);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
- fn = implicit_built_in_decls[BUILT_IN_UNWIND_RESUME];
+ fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME);
x = gimple_build_call (fn, 1, var);
gsi_insert_before (&gsi, x, GSI_SAME_STMT);
}
@@ -3206,7 +3212,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
}
else
{
- fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
+ fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
region_nr));
filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
@@ -3232,7 +3238,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
edge b_e = BRANCH_EDGE (src);
edge f_e = FALLTHRU_EDGE (src);
- fn = implicit_built_in_decls[BUILT_IN_EH_FILTER];
+ fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
region_nr));
filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
@@ -3330,7 +3336,7 @@ remove_unreachable_handlers (void)
FOR_EACH_BB (bb)
{
- gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index c8203f05752..f046363c3d4 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -387,8 +387,8 @@ emutls_common_1 (tree tls_decl, tree control_decl, tree *pstmts)
word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
- x = build_call_expr (built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON], 4,
- build_fold_addr_expr (control_decl),
+ x = build_call_expr (builtin_decl_explicit (BUILT_IN_EMUTLS_REGISTER_COMMON),
+ 4, build_fold_addr_expr (control_decl),
fold_convert (word_type_node,
DECL_SIZE_UNIT (tls_decl)),
build_int_cst (word_type_node,
@@ -434,6 +434,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d)
addr = create_tmp_var (build_pointer_type (TREE_TYPE (decl)), NULL);
x = gimple_build_call (d->builtin_decl, 1, build_fold_addr_expr (cdecl));
gimple_set_location (x, d->loc);
+ add_referenced_var (cdecl);
addr = make_ssa_name (addr, x);
gimple_call_set_lhs (x, addr);
@@ -622,7 +623,7 @@ lower_emutls_function_body (struct cgraph_node *node)
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
d.cfun_node = node;
- d.builtin_decl = built_in_decls[BUILT_IN_EMUTLS_GET_ADDRESS];
+ d.builtin_decl = builtin_decl_explicit (BUILT_IN_EMUTLS_GET_ADDRESS);
/* This is where we introduce the declaration to the IL and so we have to
create a node for it. */
d.builtin_node = cgraph_get_create_node (d.builtin_decl);
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index b9c5e16e972..56edae9fef3 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -145,16 +145,6 @@ var_ann (const_tree t)
return p ? *p : NULL;
}
-/* Return the variable annotation for T, which must be a _DECL node.
- Create the variable annotation if it doesn't exist. */
-static inline var_ann_t
-get_var_ann (tree var)
-{
- var_ann_t *p = DECL_VAR_ANN_PTR (var);
- gcc_checking_assert (p);
- return *p ? *p : create_var_ann (var);
-}
-
/* Get the number of the next statement uid to be allocated. */
static inline unsigned int
gimple_stmt_max_uid (struct function *fn)
@@ -568,7 +558,7 @@ phi_arg_index_from_use (use_operand_p use)
static inline void
set_is_used (tree var)
{
- var_ann_t ann = get_var_ann (var);
+ var_ann_t ann = var_ann (var);
ann->used = true;
}
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index d4bf54cbe69..dcfbb9da628 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -278,7 +278,6 @@ typedef struct immediate_use_iterator_d
typedef struct var_ann_d *var_ann_t;
static inline var_ann_t var_ann (const_tree);
-static inline var_ann_t get_var_ann (tree);
static inline void update_stmt (gimple);
static inline int get_lineno (const_gimple);
@@ -716,6 +715,7 @@ bool stmt_dominates_stmt_p (gimple, gimple);
void mark_virtual_ops_for_renaming (gimple);
/* In tree-ssa-dce.c */
+void mark_virtual_operand_for_renaming (tree);
void mark_virtual_phi_result_for_renaming (gimple);
/* In tree-ssa-threadedge.c */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 3610289dc35..11be8d0791f 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3285,6 +3285,7 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
??? We may consider mapping RTL costs to this. */
case COND_EXPR:
case VEC_COND_EXPR:
+ case VEC_PERM_EXPR:
case PLUS_EXPR:
case POINTER_PLUS_EXPR:
@@ -3354,6 +3355,7 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
case DOT_PROD_EXPR:
case WIDEN_MULT_PLUS_EXPR:
case WIDEN_MULT_MINUS_EXPR:
+ case WIDEN_LSHIFT_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
@@ -3368,6 +3370,8 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
case VEC_EXTRACT_ODD_EXPR:
case VEC_INTERLEAVE_HIGH_EXPR:
case VEC_INTERLEAVE_LOW_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
return 1;
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index fd633b4d320..810b974b256 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -289,7 +289,7 @@ generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
mem = force_gimple_operand (addr_base, &stmts, true, NULL);
gimple_seq_add_seq (&stmt_list, stmts);
- fn = build_fold_addr_expr (implicit_built_in_decls [BUILT_IN_MEMSET]);
+ fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
fn_call = gimple_build_call (fn, 3, mem, integer_zero_node, nb_bytes);
gimple_seq_add_stmt (&stmt_list, fn_call);
gsi_insert_seq_after (&bsi, stmt_list, GSI_CONTINUE_LINKING);
diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c
index f9b45994917..9479aebfb34 100644
--- a/gcc/tree-mudflap.c
+++ b/gcc/tree-mudflap.c
@@ -418,6 +418,10 @@ execute_mudflap_function_ops (void)
push_gimplify_context (&gctx);
+ add_referenced_var (mf_cache_array_decl);
+ add_referenced_var (mf_cache_shift_decl);
+ add_referenced_var (mf_cache_mask_decl);
+
/* In multithreaded mode, don't cache the lookup cache parameters. */
if (! flag_mudflap_threads)
mf_decl_cache_locals ();
@@ -969,7 +973,9 @@ mf_xform_statements (void)
case GIMPLE_CALL:
{
tree fndecl = gimple_call_fndecl (s);
- if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA))
+ if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
+ || (DECL_FUNCTION_CODE (fndecl)
+ == BUILT_IN_ALLOCA_WITH_ALIGN)))
gimple_call_set_cannot_inline (s, true);
}
break;
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index ef51ff48882..ae3a8dd609f 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -1811,8 +1811,8 @@ convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
x = get_frame_field (info, target_context, field, &wi->gsi);
x = build_addr (x, target_context);
x = gsi_gimplify_val (info, x, &wi->gsi);
- call = gimple_build_call (implicit_built_in_decls[BUILT_IN_NONLOCAL_GOTO], 2,
- build_addr (new_label, target_context), x);
+ call = gimple_build_call (builtin_decl_implicit (BUILT_IN_NONLOCAL_GOTO),
+ 2, build_addr (new_label, target_context), x);
gsi_replace (&wi->gsi, call, false);
/* We have handled all of STMT's operands, no need to keep going. */
@@ -1924,7 +1924,7 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
/* Do machine-specific ugliness. Normally this will involve
computing extra alignment, but it can really be anything. */
- builtin = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE];
+ builtin = builtin_decl_implicit (BUILT_IN_ADJUST_TRAMPOLINE);
call = gimple_build_call (builtin, 1, x);
x = init_tmp_var_with_call (info, &wi->gsi, call);
@@ -2399,7 +2399,7 @@ finalize_nesting_tree_1 (struct nesting_info *root)
root->frame_decl, field, NULL_TREE);
arg1 = build_addr (x, context);
- x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE];
+ x = builtin_decl_implicit (BUILT_IN_INIT_TRAMPOLINE);
stmt = gimple_build_call (x, 3, arg1, arg2, arg3);
gimple_seq_add_stmt (&stmt_list, stmt);
}
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 851bba914fa..017f8c5e933 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -166,24 +166,19 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
pt_var = TREE_OPERAND (ptr, 0);
- if (REFERENCE_CLASS_P (pt_var))
- pt_var = get_base_address (pt_var);
+ while (handled_component_p (pt_var))
+ pt_var = TREE_OPERAND (pt_var, 0);
if (pt_var
- && TREE_CODE (pt_var) == MEM_REF
- && TREE_CODE (TREE_OPERAND (pt_var, 0)) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var, 0))))
+ && TREE_CODE (pt_var) == MEM_REF)
{
unsigned HOST_WIDE_INT sz;
- if (!osi || (object_size_type & 1) != 0)
+ if (!osi || (object_size_type & 1) != 0
+ || TREE_CODE (pt_var) != SSA_NAME)
{
sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
object_size_type & ~1);
- if (host_integerp (TREE_OPERAND (pt_var, 1), 0))
- sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1));
- else
- sz = offset_limit;
}
else
{
@@ -195,10 +190,17 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
else
sz = unknown[object_size_type];
- if (host_integerp (TREE_OPERAND (pt_var, 1), 0))
- sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1));
+ }
+ if (sz != unknown[object_size_type])
+ {
+ double_int dsz = double_int_sub (uhwi_to_double_int (sz),
+ mem_ref_offset (pt_var));
+ if (double_int_negative_p (dsz))
+ sz = 0;
+ else if (double_int_fits_in_uhwi_p (dsz))
+ sz = double_int_to_uhwi (dsz);
else
- sz = offset_limit;
+ sz = unknown[object_size_type];
}
if (sz != unknown[object_size_type] && sz < offset_limit)
@@ -211,7 +213,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
tree_low_cst (DECL_SIZE_UNIT (pt_var), 1) < offset_limit)
pt_var_size = DECL_SIZE_UNIT (pt_var);
else if (pt_var
- && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
+ && TREE_CODE (pt_var) == STRING_CST
&& TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
&& host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
&& (unsigned HOST_WIDE_INT)
@@ -411,6 +413,7 @@ alloc_object_size (const_gimple call, int object_size_type)
/* fall through */
case BUILT_IN_MALLOC:
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
arg1 = 0;
default:
break;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index e30d60a365f..24d70c3ff38 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1599,6 +1599,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case RROTATE_EXPR:
case VEC_LSHIFT_EXPR:
case VEC_RSHIFT_EXPR:
+ case WIDEN_LSHIFT_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case BIT_AND_EXPR:
@@ -2069,6 +2070,16 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
pp_string (buffer, " > ");
break;
+
+ case VEC_PERM_EXPR:
+ pp_string (buffer, " VEC_PERM_EXPR < ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_string (buffer, " , ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+ pp_string (buffer, " , ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
+ pp_string (buffer, " > ");
+ break;
case DOT_PROD_EXPR:
pp_string (buffer, " DOT_PROD_EXPR < ");
@@ -2287,6 +2298,22 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_string (buffer, " > ");
break;
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+ pp_string (buffer, " > ");
+ break;
+
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+ pp_string (buffer, " > ");
+ break;
+
case VEC_UNPACK_HI_EXPR:
pp_string (buffer, " VEC_UNPACK_HI_EXPR < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
@@ -2609,6 +2636,9 @@ op_code_prio (enum tree_code code)
case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ case WIDEN_LSHIFT_EXPR:
return 11;
case WIDEN_SUM_EXPR:
@@ -2784,6 +2814,9 @@ op_symbol_code (enum tree_code code)
case VEC_RSHIFT_EXPR:
return "v>>";
+ case WIDEN_LSHIFT_EXPR:
+ return "w<<";
+
case POINTER_PLUS_EXPR:
return "+";
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index 98f7d678792..c56650c066e 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -224,6 +224,7 @@ gimple_gen_edge_profiler (int edgeno, edge e)
one = build_int_cst (gcov_type_node, 1);
stmt1 = gimple_build_assign (gcov_type_tmp_var, ref);
gimple_assign_set_lhs (stmt1, make_ssa_name (gcov_type_tmp_var, stmt1));
+ find_referenced_vars_in (stmt1);
stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, gcov_type_tmp_var,
gimple_assign_lhs (stmt1), one);
gimple_assign_set_lhs (stmt2, make_ssa_name (gcov_type_tmp_var, stmt2));
@@ -270,6 +271,7 @@ gimple_gen_interval_profiler (histogram_value value, unsigned tag, unsigned base
val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_interval_profiler_fn, 4,
ref_ptr, val, start, steps);
+ find_referenced_vars_in (call);
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
}
@@ -290,6 +292,7 @@ gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
true, NULL_TREE, true, GSI_SAME_STMT);
val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_pow2_profiler_fn, 2, ref_ptr, val);
+ find_referenced_vars_in (call);
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
}
@@ -310,6 +313,7 @@ gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned bas
true, NULL_TREE, true, GSI_SAME_STMT);
val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
+ find_referenced_vars_in (call);
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
}
@@ -340,9 +344,12 @@ gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
tmp1 = create_tmp_reg (ptr_void, "PROF");
stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr);
+ find_referenced_vars_in (stmt1);
stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
gimple_assign_set_lhs (stmt2, make_ssa_name (tmp1, stmt2));
+ find_referenced_vars_in (stmt2);
stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
+ add_referenced_var (ic_void_ptr_var);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
@@ -378,9 +385,11 @@ gimple_gen_ic_func_profiler (void)
counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
true, NULL_TREE, true,
GSI_SAME_STMT);
+ add_referenced_var (ic_gcov_type_ptr_var);
ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
true, NULL_TREE, true,
GSI_SAME_STMT);
+ add_referenced_var (ic_void_ptr_var);
tree_uid = build_int_cst (gcov_type_node, current_function_funcdef_no);
stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
counter_ptr, tree_uid, cur_func, ptr_var);
@@ -429,6 +438,7 @@ gimple_gen_average_profiler (histogram_value value, unsigned tag, unsigned base)
true, GSI_SAME_STMT);
val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_average_profiler_fn, 2, ref_ptr, val);
+ find_referenced_vars_in (call);
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
}
@@ -449,6 +459,7 @@ gimple_gen_ior_profiler (histogram_value value, unsigned tag, unsigned base)
true, NULL_TREE, true, GSI_SAME_STMT);
val = prepare_instrumented_value (&gsi, value);
call = gimple_build_call (tree_ior_profiler_fn, 2, ref_ptr, val);
+ find_referenced_vars_in (call);
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
}
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index 34479b33ae1..cf131578d2d 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -832,6 +832,68 @@ copy_mem_ref_info (tree to, tree from)
TREE_THIS_VOLATILE (to) = TREE_THIS_VOLATILE (from);
}
+/* Copies the reference information from OLD_REF to NEW_REF, where
+ NEW_REF should be either a MEM_REF or a TARGET_MEM_REF. */
+
+void
+copy_ref_info (tree new_ref, tree old_ref)
+{
+ tree new_ptr_base = NULL_TREE;
+
+ gcc_assert (TREE_CODE (new_ref) == MEM_REF
+ || TREE_CODE (new_ref) == TARGET_MEM_REF);
+
+ TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
+ TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
+
+ new_ptr_base = TREE_OPERAND (new_ref, 0);
+
+ /* We can transfer points-to information from an old pointer
+ or decl base to the new one. */
+ if (new_ptr_base
+ && TREE_CODE (new_ptr_base) == SSA_NAME
+ && !SSA_NAME_PTR_INFO (new_ptr_base))
+ {
+ tree base = get_base_address (old_ref);
+ if (!base)
+ ;
+ else if ((TREE_CODE (base) == MEM_REF
+ || TREE_CODE (base) == TARGET_MEM_REF)
+ && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
+ && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
+ {
+ struct ptr_info_def *new_pi;
+ duplicate_ssa_name_ptr_info
+ (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
+ new_pi = SSA_NAME_PTR_INFO (new_ptr_base);
+ /* We have to be careful about transfering alignment information. */
+ if (TREE_CODE (old_ref) == MEM_REF
+ && !(TREE_CODE (new_ref) == TARGET_MEM_REF
+ && (TMR_INDEX2 (new_ref)
+ || (TMR_STEP (new_ref)
+ && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
+ < new_pi->align)))))
+ {
+ new_pi->misalign += double_int_sub (mem_ref_offset (old_ref),
+ mem_ref_offset (new_ref)).low;
+ new_pi->misalign &= (new_pi->align - 1);
+ }
+ else
+ {
+ new_pi->align = 1;
+ new_pi->misalign = 0;
+ }
+ }
+ else if (TREE_CODE (base) == VAR_DECL
+ || TREE_CODE (base) == PARM_DECL
+ || TREE_CODE (base) == RESULT_DECL)
+ {
+ struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
+ pt_solution_set_var (&pi->pt, base);
+ }
+ }
+}
+
/* Move constants in target_mem_ref REF to offset. Returns the new target
mem ref if anything changes, NULL_TREE otherwise. */
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 82307decaf4..57fc7341c54 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -219,14 +219,6 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
if (!pi)
return true;
- /* If the decl can be used as a restrict tag and we have a restrict
- pointer and that pointers points-to set doesn't contain this decl
- then they can't alias. */
- if (DECL_RESTRICTED_P (decl)
- && TYPE_RESTRICT (TREE_TYPE (ptr))
- && pi->pt.vars_contains_restrict)
- return bitmap_bit_p (pi->pt.vars, DECL_PT_UID (decl));
-
return pt_solution_includes (&pi->pt, decl);
}
@@ -317,13 +309,6 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
if (!pi1 || !pi2)
return true;
- /* If both pointers are restrict-qualified try to disambiguate
- with restrict information. */
- if (TYPE_RESTRICT (TREE_TYPE (ptr1))
- && TYPE_RESTRICT (TREE_TYPE (ptr2))
- && !pt_solutions_same_restrict_base (&pi1->pt, &pi2->pt))
- return false;
-
/* ??? 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);
@@ -429,8 +414,6 @@ dump_points_to_solution (FILE *file, struct pt_solution *pt)
dump_decl_set (file, pt->vars);
if (pt->vars_contains_global)
fprintf (file, " (includes global vars)");
- if (pt->vars_contains_restrict)
- fprintf (file, " (includes restrict tags)");
}
}
@@ -1263,6 +1246,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
case BUILT_IN_MALLOC:
case BUILT_IN_CALLOC:
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
case BUILT_IN_STACK_SAVE:
case BUILT_IN_STACK_RESTORE:
case BUILT_IN_MEMSET:
@@ -1557,6 +1541,7 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
return false;
case BUILT_IN_STACK_SAVE:
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
case BUILT_IN_ASSUME_ALIGNED:
return false;
/* Freeing memory kills the pointed-to memory. More importantly
@@ -1847,6 +1832,8 @@ static bool
maybe_skip_until (gimple phi, tree target, ao_ref *ref,
tree vuse, bitmap *visited)
{
+ basic_block bb = gimple_bb (phi);
+
if (!*visited)
*visited = BITMAP_ALLOC (NULL);
@@ -1871,11 +1858,73 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
else if (gimple_nop_p (def_stmt)
|| stmt_may_clobber_ref_p_1 (def_stmt, ref))
return false;
+ /* If we reach a new basic-block see if we already skipped it
+ in a previous walk that ended successfully. */
+ if (gimple_bb (def_stmt) != bb)
+ {
+ if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (vuse)))
+ return true;
+ bb = gimple_bb (def_stmt);
+ }
vuse = gimple_vuse (def_stmt);
}
return true;
}
+/* For two PHI arguments ARG0 and ARG1 try to skip non-aliasing code
+ until we hit the phi argument definition that dominates the other one.
+ Return that, or NULL_TREE if there is no such definition. */
+
+static tree
+get_continuation_for_phi_1 (gimple phi, tree arg0, tree arg1,
+ ao_ref *ref, bitmap *visited)
+{
+ gimple def0 = SSA_NAME_DEF_STMT (arg0);
+ gimple def1 = SSA_NAME_DEF_STMT (arg1);
+ tree common_vuse;
+
+ if (arg0 == arg1)
+ return arg0;
+ else if (gimple_nop_p (def0)
+ || (!gimple_nop_p (def1)
+ && dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (def1), gimple_bb (def0))))
+ {
+ if (maybe_skip_until (phi, arg0, ref, arg1, visited))
+ return arg0;
+ }
+ else if (gimple_nop_p (def1)
+ || dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (def0), gimple_bb (def1)))
+ {
+ if (maybe_skip_until (phi, arg1, ref, arg0, visited))
+ return arg1;
+ }
+ /* Special case of a diamond:
+ MEM_1 = ...
+ goto (cond) ? L1 : L2
+ L1: store1 = ... #MEM_2 = vuse(MEM_1)
+ goto L3
+ L2: store2 = ... #MEM_3 = vuse(MEM_1)
+ L3: MEM_4 = PHI<MEM_2, MEM_3>
+ We were called with the PHI at L3, MEM_2 and MEM_3 don't
+ dominate each other, but still we can easily skip this PHI node
+ if we recognize that the vuse MEM operand is the same for both,
+ and that we can skip both statements (they don't clobber us).
+ This is still linear. Don't use maybe_skip_until, that might
+ potentially be slow. */
+ else if ((common_vuse = gimple_vuse (def0))
+ && common_vuse == gimple_vuse (def1))
+ {
+ if (!stmt_may_clobber_ref_p_1 (def0, ref)
+ && !stmt_may_clobber_ref_p_1 (def1, ref))
+ return common_vuse;
+ }
+
+ return NULL_TREE;
+}
+
+
/* Starting from a PHI node for the virtual operand of the memory reference
REF find a continuation virtual operand that allows to continue walking
statements dominating PHI skipping only statements that cannot possibly
@@ -1891,53 +1940,41 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
if (nargs == 1)
return PHI_ARG_DEF (phi, 0);
- /* For two arguments try to skip non-aliasing code until we hit
- the phi argument definition that dominates the other one. */
- if (nargs == 2)
+ /* For two or more arguments try to pairwise skip non-aliasing code
+ until we hit the phi argument definition that dominates the other one. */
+ else if (nargs >= 2)
{
- tree arg0 = PHI_ARG_DEF (phi, 0);
- tree arg1 = PHI_ARG_DEF (phi, 1);
- gimple def0 = SSA_NAME_DEF_STMT (arg0);
- gimple def1 = SSA_NAME_DEF_STMT (arg1);
- tree common_vuse;
+ tree arg0, arg1;
+ unsigned i;
+
+ /* Find a candidate for the virtual operand which definition
+ dominates those of all others. */
+ arg0 = PHI_ARG_DEF (phi, 0);
+ if (!SSA_NAME_IS_DEFAULT_DEF (arg0))
+ for (i = 1; i < nargs; ++i)
+ {
+ arg1 = PHI_ARG_DEF (phi, i);
+ if (SSA_NAME_IS_DEFAULT_DEF (arg1))
+ {
+ arg0 = arg1;
+ break;
+ }
+ if (dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (SSA_NAME_DEF_STMT (arg0)),
+ gimple_bb (SSA_NAME_DEF_STMT (arg1))))
+ arg0 = arg1;
+ }
- if (arg0 == arg1)
- return arg0;
- else if (gimple_nop_p (def0)
- || (!gimple_nop_p (def1)
- && dominated_by_p (CDI_DOMINATORS,
- gimple_bb (def1), gimple_bb (def0))))
- {
- if (maybe_skip_until (phi, arg0, ref, arg1, visited))
- return arg0;
- }
- else if (gimple_nop_p (def1)
- || dominated_by_p (CDI_DOMINATORS,
- gimple_bb (def0), gimple_bb (def1)))
+ /* Then pairwise reduce against the found candidate. */
+ for (i = 0; i < nargs; ++i)
{
- if (maybe_skip_until (phi, arg1, ref, arg0, visited))
- return arg1;
- }
- /* Special case of a diamond:
- MEM_1 = ...
- goto (cond) ? L1 : L2
- L1: store1 = ... #MEM_2 = vuse(MEM_1)
- goto L3
- L2: store2 = ... #MEM_3 = vuse(MEM_1)
- L3: MEM_4 = PHI<MEM_2, MEM_3>
- We were called with the PHI at L3, MEM_2 and MEM_3 don't
- dominate each other, but still we can easily skip this PHI node
- if we recognize that the vuse MEM operand is the same for both,
- and that we can skip both statements (they don't clobber us).
- This is still linear. Don't use maybe_skip_until, that might
- potentially be slow. */
- else if ((common_vuse = gimple_vuse (def0))
- && common_vuse == gimple_vuse (def1))
- {
- if (!stmt_may_clobber_ref_p_1 (def0, ref)
- && !stmt_may_clobber_ref_p_1 (def1, ref))
- return common_vuse;
+ arg1 = PHI_ARG_DEF (phi, i);
+ arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref, visited);
+ if (!arg0)
+ return NULL_TREE;
}
+
+ return arg0;
}
return NULL_TREE;
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index c2ab2113c1e..74921231045 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -54,8 +54,6 @@ struct GTY(()) pt_solution
/* Nonzero if the pt_vars bitmap includes a global variable. */
unsigned int vars_contains_global : 1;
- /* Nonzero if the pt_vars bitmap includes a restrict tag variable. */
- unsigned int vars_contains_restrict : 1;
/* Set of variables that this pointer may point to. */
bitmap vars;
@@ -130,10 +128,8 @@ extern bool pt_solution_singleton_p (struct pt_solution *, unsigned *);
extern bool pt_solution_includes_global (struct pt_solution *);
extern bool pt_solution_includes (struct pt_solution *, const_tree);
extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
-extern bool pt_solutions_same_restrict_base (struct pt_solution *,
- struct pt_solution *);
extern void pt_solution_reset (struct pt_solution *);
-extern void pt_solution_set (struct pt_solution *, bitmap, bool, bool);
+extern void pt_solution_set (struct pt_solution *, bitmap, bool);
extern void pt_solution_set_var (struct pt_solution *, tree);
extern void dump_pta_stats (FILE *);
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index b5774040e32..31c31c141c9 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1492,6 +1492,7 @@ evaluate_stmt (gimple stmt)
tree simplified = NULL_TREE;
ccp_lattice_t likelyvalue = likely_value (stmt);
bool is_constant = false;
+ unsigned int align;
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1632,10 +1633,14 @@ evaluate_stmt (gimple stmt)
break;
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ align = (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN
+ ? TREE_INT_CST_LOW (gimple_call_arg (stmt, 1))
+ : BIGGEST_ALIGNMENT);
val.lattice_val = CONSTANT;
val.value = build_int_cst (TREE_TYPE (gimple_get_lhs (stmt)), 0);
val.mask = shwi_to_double_int
- (~(((HOST_WIDE_INT) BIGGEST_ALIGNMENT)
+ (~(((HOST_WIDE_INT) align)
/ BITS_PER_UNIT - 1));
break;
@@ -1685,15 +1690,15 @@ evaluate_stmt (gimple stmt)
return val;
}
-/* Detects a vla-related alloca with a constant argument. Declares fixed-size
- array and return the address, if found, otherwise returns NULL_TREE. */
+/* Detects a __builtin_alloca_with_align with constant size argument. Declares
+ fixed-size array and returns the address, if found, otherwise returns
+ NULL_TREE. */
static tree
-fold_builtin_alloca_for_var (gimple stmt)
+fold_builtin_alloca_with_align (gimple stmt)
{
unsigned HOST_WIDE_INT size, threshold, n_elem;
tree lhs, arg, block, var, elem_type, array_type;
- unsigned int align;
/* Get lhs. */
lhs = gimple_call_lhs (stmt);
@@ -1709,10 +1714,10 @@ fold_builtin_alloca_for_var (gimple stmt)
size = TREE_INT_CST_LOW (arg);
- /* Heuristic: don't fold large vlas. */
+ /* Heuristic: don't fold large allocas. */
threshold = (unsigned HOST_WIDE_INT)PARAM_VALUE (PARAM_LARGE_STACK_FRAME);
- /* In case a vla is declared at function scope, it has the same lifetime as a
- declared array, so we allow a larger size. */
+ /* In case the alloca is located at function entry, it has the same lifetime
+ as a declared array, so we allow a larger size. */
block = gimple_block (stmt);
if (!(cfun->after_inlining
&& TREE_CODE (BLOCK_SUPERCONTEXT (block)) == FUNCTION_DECL))
@@ -1723,12 +1728,9 @@ fold_builtin_alloca_for_var (gimple stmt)
/* Declare array. */
elem_type = build_nonstandard_integer_type (BITS_PER_UNIT, 1);
n_elem = size * 8 / BITS_PER_UNIT;
- align = MIN (size * 8, BIGGEST_ALIGNMENT);
- if (align < BITS_PER_UNIT)
- align = BITS_PER_UNIT;
array_type = build_array_type_nelts (elem_type, n_elem);
var = create_tmp_var (array_type, NULL);
- DECL_ALIGN (var) = align;
+ DECL_ALIGN (var) = TREE_INT_CST_LOW (gimple_call_arg (stmt, 1));
{
struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
if (pi != NULL && !pi->pt.anything)
@@ -1813,12 +1815,12 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
if (gimple_call_internal_p (stmt))
return false;
- /* The heuristic of fold_builtin_alloca_for_var differs before and after
- inlining, so we don't require the arg to be changed into a constant
- for folding, but just to be constant. */
- if (gimple_call_alloca_for_var_p (stmt))
+ /* The heuristic of fold_builtin_alloca_with_align differs before and
+ after inlining, so we don't require the arg to be changed into a
+ constant for folding, but just to be constant. */
+ if (gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
{
- tree new_rhs = fold_builtin_alloca_for_var (stmt);
+ tree new_rhs = fold_builtin_alloca_with_align (stmt);
if (new_rhs)
{
bool res = update_call_from_tree (gsi, new_rhs);
@@ -2093,7 +2095,8 @@ optimize_stack_restore (gimple_stmt_iterator i)
if (!callee
|| DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
/* All regular builtins are ok, just obviously not alloca. */
- || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA)
+ || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
+ || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA_WITH_ALIGN)
return NULL_TREE;
if (DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE)
@@ -2172,7 +2175,7 @@ optimize_stdarg_builtin (gimple call)
case BUILT_IN_VA_START:
if (!va_list_simple_ptr
|| targetm.expand_builtin_va_start != NULL
- || built_in_decls[BUILT_IN_NEXT_ARG] == NULL)
+ || builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
return NULL_TREE;
if (gimple_call_num_args (call) != 2)
@@ -2185,7 +2188,7 @@ optimize_stdarg_builtin (gimple call)
return NULL_TREE;
lhs = build_fold_indirect_ref_loc (loc, lhs);
- rhs = build_call_expr_loc (loc, built_in_decls[BUILT_IN_NEXT_ARG],
+ rhs = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_NEXT_ARG),
1, integer_zero_node);
rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index f225030de68..5a6a38e63e9 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -308,6 +308,7 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
case BUILT_IN_MALLOC:
case BUILT_IN_CALLOC:
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
return;
default:;
@@ -639,6 +640,7 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
case BUILT_IN_MALLOC:
case BUILT_IN_CALLOC:
case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
case BUILT_IN_FREE:
return false;
@@ -890,6 +892,8 @@ propagate_necessity (struct edge_list *el)
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_END
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
+ || (DECL_FUNCTION_CODE (callee)
+ == BUILT_IN_ALLOCA_WITH_ALIGN)
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
@@ -978,18 +982,36 @@ propagate_necessity (struct edge_list *el)
}
}
-/* Replace all uses of result of PHI by underlying variable and mark it
+/* Replace all uses of NAME by underlying variable and mark it
for renaming. */
void
-mark_virtual_phi_result_for_renaming (gimple phi)
+mark_virtual_operand_for_renaming (tree name)
{
bool used = false;
imm_use_iterator iter;
use_operand_p use_p;
gimple stmt;
- tree result_ssa, result_var;
+ tree name_var;
+
+ name_var = SSA_NAME_VAR (name);
+ FOR_EACH_IMM_USE_STMT (stmt, iter, name)
+ {
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, name_var);
+ update_stmt (stmt);
+ used = true;
+ }
+ if (used)
+ mark_sym_for_renaming (name_var);
+}
+/* Replace all uses of result of PHI by underlying variable and mark it
+ for renaming. */
+
+void
+mark_virtual_phi_result_for_renaming (gimple phi)
+{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Marking result for renaming : ");
@@ -997,19 +1019,10 @@ mark_virtual_phi_result_for_renaming (gimple phi)
fprintf (dump_file, "\n");
}
- result_ssa = gimple_phi_result (phi);
- result_var = SSA_NAME_VAR (result_ssa);
- FOR_EACH_IMM_USE_STMT (stmt, iter, result_ssa)
- {
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, result_var);
- update_stmt (stmt);
- used = true;
- }
- if (used)
- mark_sym_for_renaming (result_var);
+ mark_virtual_operand_for_renaming (gimple_phi_result (phi));
}
+
/* Remove dead PHI nodes from block BB. */
static bool
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 3902b5ce5c9..8bfc91aae4f 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1995,17 +1995,6 @@ cprop_operand (gimple stmt, use_operand_p op_p)
val = SSA_NAME_VALUE (op);
if (val && val != op)
{
- /* Do not change the base variable in the virtual operand
- tables. That would make it impossible to reconstruct
- the renamed virtual operand if we later modify this
- statement. Also only allow the new value to be an SSA_NAME
- for propagation into virtual operands. */
- if (!is_gimple_reg (op)
- && (TREE_CODE (val) != SSA_NAME
- || is_gimple_reg (val)
- || get_virtual_var (val) != get_virtual_var (op)))
- return;
-
/* Do not replace hard register operands in asm statements. */
if (gimple_code (stmt) == GIMPLE_ASM
&& !may_propagate_copy_into_asm (op))
@@ -2076,11 +2065,8 @@ cprop_into_stmt (gimple stmt)
use_operand_p op_p;
ssa_op_iter iter;
- FOR_EACH_SSA_USE_OPERAND (op_p, stmt, iter, SSA_OP_ALL_USES)
- {
- if (TREE_CODE (USE_FROM_PTR (op_p)) == SSA_NAME)
- cprop_operand (stmt, op_p);
- }
+ FOR_EACH_SSA_USE_OPERAND (op_p, stmt, iter, SSA_OP_USE)
+ cprop_operand (stmt, op_p);
}
/* Optimize the statement pointed to by iterator SI.
@@ -2107,18 +2093,18 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si)
old_stmt = stmt = gsi_stmt (si);
- if (gimple_code (stmt) == GIMPLE_COND)
- canonicalize_comparison (stmt);
-
- update_stmt_if_modified (stmt);
- opt_stats.num_stmts++;
-
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Optimizing statement ");
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
+ if (gimple_code (stmt) == GIMPLE_COND)
+ canonicalize_comparison (stmt);
+
+ update_stmt_if_modified (stmt);
+ opt_stats.num_stmts++;
+
/* Const/copy propagate into USES, VUSES and the RHS of VDEFs. */
cprop_into_stmt (stmt);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index a8737dac933..d707db520e3 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -465,16 +465,15 @@ forward_propagate_into_comparison (gimple_stmt_iterator *gsi)
gimple stmt = gsi_stmt (*gsi);
tree tmp;
bool cfg_changed = false;
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs2 = gimple_assign_rhs2 (stmt);
/* Combine the comparison with defining statements. */
tmp = forward_propagate_into_comparison_1 (stmt,
gimple_assign_rhs_code (stmt),
- TREE_TYPE
- (gimple_assign_lhs (stmt)),
- rhs1, rhs2);
- if (tmp)
+ type, rhs1, rhs2);
+ if (tmp && useless_type_conversion_p (type, TREE_TYPE (tmp)))
{
gimple_assign_set_rhs_from_tree (gsi, tmp);
fold_stmt (gsi);
@@ -598,7 +597,8 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
}
}
- if (tmp)
+ if (tmp
+ && is_gimple_condexpr (tmp))
{
if (dump_file && tmp)
{
@@ -1596,7 +1596,8 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
if (!is_gimple_val (ptr1))
ptr1 = force_gimple_operand_gsi (gsi_p, ptr1, true, NULL_TREE,
true, GSI_SAME_STMT);
- gimple_call_set_fndecl (stmt2, built_in_decls [BUILT_IN_MEMCPY]);
+ gimple_call_set_fndecl (stmt2,
+ builtin_decl_explicit (BUILT_IN_MEMCPY));
gimple_call_set_arg (stmt2, 0, ptr1);
gimple_call_set_arg (stmt2, 1, new_str_cst);
gimple_call_set_arg (stmt2, 2,
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 67d04647c8b..15a2dd7bc58 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -6278,64 +6278,6 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
}
}
-/* Copies the reference information from OLD_REF to NEW_REF. */
-
-static void
-copy_ref_info (tree new_ref, tree old_ref)
-{
- tree new_ptr_base = NULL_TREE;
-
- TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
- TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
-
- new_ptr_base = TREE_OPERAND (new_ref, 0);
-
- /* We can transfer points-to information from an old pointer
- or decl base to the new one. */
- if (new_ptr_base
- && TREE_CODE (new_ptr_base) == SSA_NAME
- && !SSA_NAME_PTR_INFO (new_ptr_base))
- {
- tree base = get_base_address (old_ref);
- if (!base)
- ;
- else if ((TREE_CODE (base) == MEM_REF
- || TREE_CODE (base) == TARGET_MEM_REF)
- && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
- && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
- {
- struct ptr_info_def *new_pi;
- duplicate_ssa_name_ptr_info
- (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
- new_pi = SSA_NAME_PTR_INFO (new_ptr_base);
- /* We have to be careful about transfering alignment information. */
- if (TREE_CODE (old_ref) == MEM_REF
- && !(TREE_CODE (new_ref) == TARGET_MEM_REF
- && (TMR_INDEX2 (new_ref)
- || (TMR_STEP (new_ref)
- && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
- < new_pi->align)))))
- {
- new_pi->misalign += double_int_sub (mem_ref_offset (old_ref),
- mem_ref_offset (new_ref)).low;
- new_pi->misalign &= (new_pi->align - 1);
- }
- else
- {
- new_pi->align = 1;
- new_pi->misalign = 0;
- }
- }
- else if (TREE_CODE (base) == VAR_DECL
- || TREE_CODE (base) == PARM_DECL
- || TREE_CODE (base) == RESULT_DECL)
- {
- struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
- pt_solution_set_var (&pi->pt, base);
- }
- }
-}
-
/* Performs a peephole optimization to reorder the iv update statement with
a mem ref to enable instruction combining in later phases. The mem ref uses
the iv value before the update, so the reordering transformation requires
diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
index c5ad1c4765f..264d97bc1b5 100644
--- a/gcc/tree-ssa-loop-prefetch.c
+++ b/gcc/tree-ssa-loop-prefetch.c
@@ -1117,7 +1117,7 @@ issue_prefetch_ref (struct mem_ref *ref, unsigned unroll_factor, unsigned ahead)
NULL, true, GSI_SAME_STMT);
}
/* Create the prefetch instruction. */
- prefetch = gimple_build_call (built_in_decls[BUILT_IN_PREFETCH],
+ prefetch = gimple_build_call (builtin_decl_explicit (BUILT_IN_PREFETCH),
3, addr, write_p, local);
gsi_insert_before (&bsi, prefetch, GSI_SAME_STMT);
}
@@ -1909,7 +1909,7 @@ tree_ssa_prefetch_arrays (void)
initialize_original_copy_tables ();
- if (!built_in_decls[BUILT_IN_PREFETCH])
+ if (!builtin_decl_explicit_p (BUILT_IN_PREFETCH))
{
tree type = build_function_type_list (void_type_node,
const_ptr_type_node, NULL_TREE);
@@ -1917,7 +1917,7 @@ tree_ssa_prefetch_arrays (void)
BUILT_IN_PREFETCH, BUILT_IN_NORMAL,
NULL, NULL_TREE);
DECL_IS_NOVOPS (decl) = true;
- built_in_decls[BUILT_IN_PREFETCH] = decl;
+ set_builtin_decl (BUILT_IN_PREFETCH, decl, false);
}
/* We assume that size of cache line is a power of two, so verify this
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index ed99802b3b2..75abb3369a1 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -1805,9 +1805,9 @@ execute_optimize_bswap (void)
if (sizeof (HOST_WIDEST_INT) < 8)
return 0;
- bswap32_p = (built_in_decls[BUILT_IN_BSWAP32]
+ bswap32_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP32)
&& optab_handler (bswap_optab, SImode) != CODE_FOR_nothing);
- bswap64_p = (built_in_decls[BUILT_IN_BSWAP64]
+ bswap64_p = (builtin_decl_explicit_p (BUILT_IN_BSWAP64)
&& (optab_handler (bswap_optab, DImode) != CODE_FOR_nothing
|| (bswap32_p && word_mode == SImode)));
@@ -1818,13 +1818,13 @@ execute_optimize_bswap (void)
assumes that the return and argument type are the same. */
if (bswap32_p)
{
- tree fndecl = built_in_decls[BUILT_IN_BSWAP32];
+ tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
bswap32_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
}
if (bswap64_p)
{
- tree fndecl = built_in_decls[BUILT_IN_BSWAP64];
+ tree fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
}
@@ -1858,14 +1858,14 @@ execute_optimize_bswap (void)
case 32:
if (bswap32_p)
{
- fndecl = built_in_decls[BUILT_IN_BSWAP32];
+ fndecl = builtin_decl_explicit (BUILT_IN_BSWAP32);
bswap_type = bswap32_type;
}
break;
case 64:
if (bswap64_p)
{
- fndecl = built_in_decls[BUILT_IN_BSWAP64];
+ fndecl = builtin_decl_explicit (BUILT_IN_BSWAP64);
bswap_type = bswap64_type;
}
break;
@@ -2039,10 +2039,12 @@ is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
and *TYPE2_OUT would give the operands of the multiplication. */
static bool
-is_widening_mult_p (tree type, gimple stmt,
+is_widening_mult_p (gimple stmt,
tree *type1_out, tree *rhs1_out,
tree *type2_out, tree *rhs2_out)
{
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+
if (TREE_CODE (type) != INTEGER_TYPE
&& TREE_CODE (type) != FIXED_POINT_TYPE)
return false;
@@ -2104,7 +2106,7 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
if (TREE_CODE (type) != INTEGER_TYPE)
return false;
- if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2))
+ if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
return false;
to_mode = TYPE_MODE (type);
@@ -2281,7 +2283,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
if (code == PLUS_EXPR
&& (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
{
- if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1,
+ if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
&type2, &mult_rhs2))
return false;
add_rhs = rhs2;
@@ -2289,7 +2291,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
}
else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
{
- if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1,
+ if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
&type2, &mult_rhs2))
return false;
add_rhs = rhs1;
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index f27d5f0e6c0..9cd656b2a8c 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -943,6 +943,7 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
case COND_EXPR:
case VEC_COND_EXPR:
+ case VEC_PERM_EXPR:
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), uflags);
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index a7f6cee35d8..60ae35cef73 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3188,7 +3188,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
/* Fold the last statement. */
gsi = gsi_last (*stmts);
- fold_stmt_inplace (&gsi);
+ if (fold_stmt_inplace (&gsi))
+ update_stmt (gsi_stmt (gsi));
/* Add a value number to the temporary.
The value may already exist in either NEW_SETS, or AVAIL_OUT, because
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index f7c21e70eb8..554ba3abe76 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -1648,6 +1648,8 @@ init_range_entry (struct range_entry *r, tree exp)
code = gimple_assign_rhs_code (stmt);
arg0 = gimple_assign_rhs1 (stmt);
+ if (TREE_CODE (arg0) != SSA_NAME)
+ break;
arg1 = gimple_assign_rhs2 (stmt);
exp_type = TREE_TYPE (exp);
loc = gimple_location (stmt);
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 003804b3ca8..c33b87dd7fe 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -275,6 +275,13 @@ vn_get_expr_for (tree name)
gimple_assign_rhs2 (def_stmt));
break;
+ case tcc_exceptional:
+ if (code == CONSTRUCTOR
+ && TREE_CODE
+ (TREE_TYPE (gimple_assign_rhs1 (def_stmt))) == VECTOR_TYPE)
+ expr = gimple_assign_rhs1 (def_stmt);
+ break;
+
default:;
}
if (expr == NULL_TREE)
@@ -1435,7 +1442,113 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
}
}
- /* 3) For aggregate copies translate the reference through them if
+ /* 3) Assignment from a constant. We can use folds native encode/interpret
+ routines to extract the assigned bits. */
+ else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
+ && ref->size == maxsize
+ && maxsize % BITS_PER_UNIT == 0
+ && offset % BITS_PER_UNIT == 0
+ && is_gimple_reg_type (vr->type)
+ && gimple_assign_single_p (def_stmt)
+ && is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt)))
+ {
+ tree base2;
+ HOST_WIDE_INT offset2, size2, maxsize2;
+ base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
+ &offset2, &size2, &maxsize2);
+ if (maxsize2 != -1
+ && maxsize2 == size2
+ && size2 % BITS_PER_UNIT == 0
+ && offset2 % BITS_PER_UNIT == 0
+ && operand_equal_p (base, base2, 0)
+ && offset2 <= offset
+ && offset2 + size2 >= offset + maxsize)
+ {
+ /* We support up to 512-bit values (for V8DFmode). */
+ unsigned char buffer[64];
+ int len;
+
+ len = native_encode_expr (gimple_assign_rhs1 (def_stmt),
+ buffer, sizeof (buffer));
+ if (len > 0)
+ {
+ tree val = native_interpret_expr (vr->type,
+ buffer
+ + ((offset - offset2)
+ / BITS_PER_UNIT),
+ ref->size / BITS_PER_UNIT);
+ if (val)
+ {
+ 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);
+ }
+ }
+ }
+ }
+
+ /* 4) Assignment from an SSA name which definition we may be able
+ to access pieces from. */
+ else if (ref->size == maxsize
+ && is_gimple_reg_type (vr->type)
+ && gimple_assign_single_p (def_stmt)
+ && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME)
+ {
+ tree rhs1 = gimple_assign_rhs1 (def_stmt);
+ gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs1);
+ if (is_gimple_assign (def_stmt2)
+ && (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR
+ || gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR)
+ && types_compatible_p (vr->type, TREE_TYPE (TREE_TYPE (rhs1))))
+ {
+ tree base2;
+ HOST_WIDE_INT offset2, size2, maxsize2, off;
+ base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
+ &offset2, &size2, &maxsize2);
+ off = offset - offset2;
+ if (maxsize2 != -1
+ && maxsize2 == size2
+ && operand_equal_p (base, base2, 0)
+ && offset2 <= offset
+ && offset2 + size2 >= offset + maxsize)
+ {
+ tree val = NULL_TREE;
+ HOST_WIDE_INT elsz
+ = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (TREE_TYPE (rhs1))));
+ if (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR)
+ {
+ if (off == 0)
+ val = gimple_assign_rhs1 (def_stmt2);
+ else if (off == elsz)
+ val = gimple_assign_rhs2 (def_stmt2);
+ }
+ else if (gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR
+ && off % elsz == 0)
+ {
+ tree ctor = gimple_assign_rhs1 (def_stmt2);
+ unsigned i = off / elsz;
+ if (i < CONSTRUCTOR_NELTS (ctor))
+ {
+ constructor_elt *elt = CONSTRUCTOR_ELT (ctor, i);
+ if (compare_tree_int (elt->index, i) == 0)
+ val = elt->value;
+ }
+ }
+ if (val)
+ {
+ 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);
+ }
+ }
+ }
+ }
+
+ /* 5) For aggregate copies translate the reference through them if
the copy kills ref. */
else if (vn_walk_kind == VN_WALKREWRITE
&& gimple_assign_single_p (def_stmt)
@@ -1533,7 +1646,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
return NULL;
}
- /* 4) For memcpy copies translate the reference through them if
+ /* 6) For memcpy copies translate the reference through them if
the copy kills ref. */
else if (vn_walk_kind == VN_WALKREWRITE
&& is_gimple_reg_type (vr->type)
@@ -2922,7 +3035,8 @@ simplify_unary_expression (gimple stmt)
GIMPLE_ASSIGN_SINGLE codes. */
if (code == REALPART_EXPR
|| code == IMAGPART_EXPR
- || code == VIEW_CONVERT_EXPR)
+ || code == VIEW_CONVERT_EXPR
+ || code == BIT_FIELD_REF)
op0 = TREE_OPERAND (op0, 0);
if (TREE_CODE (op0) != SSA_NAME)
@@ -2934,7 +3048,8 @@ simplify_unary_expression (gimple stmt)
else if (CONVERT_EXPR_CODE_P (code)
|| code == REALPART_EXPR
|| code == IMAGPART_EXPR
- || code == VIEW_CONVERT_EXPR)
+ || code == VIEW_CONVERT_EXPR
+ || code == BIT_FIELD_REF)
{
/* We want to do tree-combining on conversion-like expressions.
Make sure we feed only SSA_NAMEs or constants to fold though. */
@@ -2943,6 +3058,7 @@ simplify_unary_expression (gimple stmt)
|| BINARY_CLASS_P (tem)
|| TREE_CODE (tem) == VIEW_CONVERT_EXPR
|| TREE_CODE (tem) == SSA_NAME
+ || TREE_CODE (tem) == CONSTRUCTOR
|| is_gimple_min_invariant (tem))
op0 = tem;
}
@@ -2951,7 +3067,14 @@ simplify_unary_expression (gimple stmt)
if (op0 == orig_op0)
return NULL_TREE;
- result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0);
+ if (code == BIT_FIELD_REF)
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+ result = fold_ternary (BIT_FIELD_REF, TREE_TYPE (rhs),
+ op0, TREE_OPERAND (rhs, 1), TREE_OPERAND (rhs, 2));
+ }
+ else
+ result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0);
if (result)
{
STRIP_USELESS_TYPE_CONVERSION (result);
@@ -2967,27 +3090,30 @@ simplify_unary_expression (gimple stmt)
static tree
try_to_simplify (gimple stmt)
{
+ enum tree_code code = gimple_assign_rhs_code (stmt);
tree tem;
/* For stores we can end up simplifying a SSA_NAME rhs. Just return
in this case, there is no point in doing extra work. */
- if (gimple_assign_copy_p (stmt)
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
+ if (code == SSA_NAME)
return NULL_TREE;
/* First try constant folding based on our current lattice. */
- tem = gimple_fold_stmt_to_constant (stmt, vn_valueize);
- if (tem)
+ tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize);
+ if (tem
+ && (TREE_CODE (tem) == SSA_NAME
+ || is_gimple_min_invariant (tem)))
return tem;
/* If that didn't work try combining multiple statements. */
- switch (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)))
+ switch (TREE_CODE_CLASS (code))
{
case tcc_reference:
- /* Fallthrough for some codes that can operate on registers. */
- if (!(TREE_CODE (gimple_assign_rhs1 (stmt)) == REALPART_EXPR
- || TREE_CODE (gimple_assign_rhs1 (stmt)) == IMAGPART_EXPR
- || TREE_CODE (gimple_assign_rhs1 (stmt)) == VIEW_CONVERT_EXPR))
+ /* Fallthrough for some unary codes that can operate on registers. */
+ if (!(code == REALPART_EXPR
+ || code == IMAGPART_EXPR
+ || code == VIEW_CONVERT_EXPR
+ || code == BIT_FIELD_REF))
break;
/* We could do a little more with unary ops, if they expand
into binary ops, but it's debatable whether it is worth it. */
@@ -3157,7 +3283,8 @@ visit_use (tree use)
/* VOP-less references can go through unary case. */
if ((code == REALPART_EXPR
|| code == IMAGPART_EXPR
- || code == VIEW_CONVERT_EXPR)
+ || code == VIEW_CONVERT_EXPR
+ || code == BIT_FIELD_REF)
&& TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
{
changed = visit_nary_op (lhs, stmt);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 71cefaaabc8..697340f535a 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -397,7 +397,7 @@ get_string_length (strinfo si)
callee = gimple_call_fndecl (stmt);
gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
lhs = gimple_call_lhs (stmt);
- gcc_assert (implicit_built_in_decls[BUILT_IN_STRCPY] != NULL_TREE);
+ gcc_assert (builtin_decl_implicit_p (BUILT_IN_STRCPY));
/* unshare_strinfo is intentionally not called here. The (delayed)
transformation of strcpy or strcat into stpcpy is done at the place
of the former strcpy/strcat call and so can affect all the strinfos
@@ -409,7 +409,7 @@ get_string_length (strinfo si)
case BUILT_IN_STRCAT:
case BUILT_IN_STRCAT_CHK:
gsi = gsi_for_stmt (stmt);
- fn = implicit_built_in_decls[BUILT_IN_STRLEN];
+ fn = builtin_decl_implicit (BUILT_IN_STRLEN);
gcc_assert (lhs == NULL_TREE);
lhs_var = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
add_referenced_var (lhs_var);
@@ -434,9 +434,9 @@ get_string_length (strinfo si)
case BUILT_IN_STRCPY:
case BUILT_IN_STRCPY_CHK:
if (gimple_call_num_args (stmt) == 2)
- fn = implicit_built_in_decls[BUILT_IN_STPCPY];
+ fn = builtin_decl_implicit (BUILT_IN_STPCPY);
else
- fn = built_in_decls[BUILT_IN_STPCPY_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_STPCPY_CHK);
gcc_assert (lhs == NULL_TREE);
if (dump_file && (dump_flags & TDF_DETAILS) != 0)
{
@@ -692,6 +692,14 @@ find_equal_ptrs (tree ptr, int idx)
{
case SSA_NAME:
break;
+ CASE_CONVERT:
+ if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
+ return;
+ if (TREE_CODE (ptr) == SSA_NAME)
+ break;
+ if (TREE_CODE (ptr) != ADDR_EXPR)
+ return;
+ /* FALLTHRU */
case ADDR_EXPR:
{
int *pidx = addr_stridxptr (TREE_OPERAND (ptr, 0));
@@ -699,10 +707,6 @@ find_equal_ptrs (tree ptr, int idx)
*pidx = idx;
return;
}
- CASE_CONVERT:
- if (POINTER_TYPE_P (TREE_TYPE (ptr)))
- break;
- return;
default:
return;
}
@@ -1066,8 +1070,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
{
case BUILT_IN_STRCPY:
case BUILT_IN_STRCPY_CHK:
- if (implicit_built_in_decls[BUILT_IN_STPCPY] == NULL_TREE
- || lhs != NULL_TREE)
+ if (lhs != NULL_TREE || !builtin_decl_implicit_p (BUILT_IN_STPCPY))
return;
break;
case BUILT_IN_STPCPY:
@@ -1150,12 +1153,12 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
switch (bcode)
{
case BUILT_IN_STRCPY:
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
if (lhs)
VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
break;
case BUILT_IN_STRCPY_CHK:
- fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
if (lhs)
VEC_replace (int, ssa_ver_to_stridx, SSA_NAME_VERSION (lhs), didx);
break;
@@ -1163,7 +1166,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
/* This would need adjustment of the lhs (subtract one),
or detection that the trailing '\0' doesn't need to be
written, if it will be immediately overwritten.
- fn = built_in_decls[BUILT_IN_MEMPCPY]; */
+ fn = builtin_decl_explicit (BUILT_IN_MEMPCPY); */
if (lhs)
{
dsi->endptr = lhs;
@@ -1174,7 +1177,7 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
/* This would need adjustment of the lhs (subtract one),
or detection that the trailing '\0' doesn't need to be
written, if it will be immediately overwritten.
- fn = built_in_decls[BUILT_IN_MEMPCPY_CHK]; */
+ fn = builtin_decl_explicit (BUILT_IN_MEMPCPY_CHK); */
if (lhs)
{
dsi->endptr = lhs;
@@ -1297,7 +1300,7 @@ handle_builtin_memcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (si != NULL)
newlen = si->length;
else
- newlen = build_int_cst (TREE_TYPE (len), ~idx);
+ newlen = build_int_cst (size_type_node, ~idx);
oldlen = NULL_TREE;
if (olddsi != NULL)
{
@@ -1396,8 +1399,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
with length endptr - p if we need to compute the length
later on. Don't do this transformation if we don't need
it. */
- if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
- && lhs == NULL_TREE)
+ if (builtin_decl_implicit_p (BUILT_IN_STPCPY) && lhs == NULL_TREE)
{
if (didx == 0)
{
@@ -1456,8 +1458,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
else
{
dsi->length = NULL;
- if (implicit_built_in_decls[BUILT_IN_STPCPY] != NULL_TREE
- && lhs == NULL_TREE)
+ if (lhs == NULL_TREE && builtin_decl_implicit_p (BUILT_IN_STPCPY))
dsi->dont_invalidate = true;
}
@@ -1477,15 +1478,15 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi)
{
case BUILT_IN_STRCAT:
if (srclen != NULL_TREE)
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
else
- fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ fn = builtin_decl_implicit (BUILT_IN_STRCPY);
break;
case BUILT_IN_STRCAT_CHK:
if (srclen != NULL_TREE)
- fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_MEMCPY_CHK);
else
- fn = built_in_decls[BUILT_IN_STRCPY_CHK];
+ fn = builtin_decl_explicit (BUILT_IN_STRCPY_CHK);
objsz = gimple_call_arg (stmt, 2);
break;
default:
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 821fc7d92b2..51f2aa1bf7c 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -261,9 +261,6 @@ struct variable_info
/* True if this is a heap variable. */
unsigned int is_heap_var : 1;
- /* True if this is a variable tracking a restrict pointer source. */
- unsigned int is_restrict_var : 1;
-
/* True if this field may contain pointers. */
unsigned int may_have_pointers : 1;
@@ -350,7 +347,6 @@ new_var_info (tree t, const char *name)
ret->is_unknown_size_var = false;
ret->is_full_var = (t == NULL_TREE);
ret->is_heap_var = false;
- ret->is_restrict_var = false;
ret->may_have_pointers = true;
ret->only_restrict_pointers = false;
ret->is_global_var = (t == NULL_TREE);
@@ -3643,30 +3639,30 @@ make_heapvar (const char *name)
}
/* Create a new artificial heap variable with NAME and make a
- constraint from it to LHS. Return the created variable. */
+ constraint from it to LHS. Set flags according to a tag used
+ for tracking restrict pointers. */
static varinfo_t
-make_constraint_from_heapvar (varinfo_t lhs, const char *name)
+make_constraint_from_restrict (varinfo_t lhs, const char *name)
{
varinfo_t vi = make_heapvar (name);
+ vi->is_global_var = 1;
+ vi->may_have_pointers = 1;
make_constraint_from (lhs, vi->id);
-
return vi;
}
/* Create a new artificial heap variable with NAME and make a
constraint from it to LHS. Set flags according to a tag used
- for tracking restrict pointers. */
+ for tracking restrict pointers and make the artificial heap
+ point to global memory. */
-static void
-make_constraint_from_restrict (varinfo_t lhs, const char *name)
+static varinfo_t
+make_constraint_from_global_restrict (varinfo_t lhs, const char *name)
{
- varinfo_t vi;
- vi = make_constraint_from_heapvar (lhs, name);
- vi->is_restrict_var = 1;
- vi->is_global_var = 0;
- vi->is_special_var = 1;
- vi->may_have_pointers = 0;
+ varinfo_t vi = make_constraint_from_restrict (lhs, name);
+ make_copy_constraint (vi, nonlocal_id);
+ return vi;
}
/* In IPA mode there are varinfos for different aspects of reach
@@ -4494,15 +4490,6 @@ find_func_aliases (gimple origt)
&& (!in_ipa_mode
|| DECL_EXTERNAL (lhsop) || TREE_PUBLIC (lhsop)))
make_escape_constraint (rhsop);
- /* If this is a conversion of a non-restrict pointer to a
- restrict pointer track it with a new heapvar. */
- else if (gimple_assign_cast_p (t)
- && POINTER_TYPE_P (TREE_TYPE (rhsop))
- && POINTER_TYPE_P (TREE_TYPE (lhsop))
- && !TYPE_RESTRICT (TREE_TYPE (rhsop))
- && TYPE_RESTRICT (TREE_TYPE (lhsop)))
- make_constraint_from_restrict (get_vi_for_tree (lhsop),
- "CAST_RESTRICT");
}
/* Handle escapes through return. */
else if (gimple_code (t) == GIMPLE_RETURN
@@ -5513,13 +5500,18 @@ create_variable_info_for (tree decl, const char *name)
if ((POINTER_TYPE_P (TREE_TYPE (decl))
&& TYPE_RESTRICT (TREE_TYPE (decl)))
|| vi->only_restrict_pointers)
- make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
+ {
+ make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ continue;
+ }
/* In non-IPA mode the initializer from nonlocal is all we need. */
if (!in_ipa_mode
|| DECL_HARD_REGISTER (decl))
make_copy_constraint (vi, nonlocal_id);
+ /* In IPA mode parse the initializer and generate proper constraints
+ for it. */
else
{
struct varpool_node *vnode = varpool_get_node (decl);
@@ -5604,7 +5596,7 @@ intra_create_variable_infos (void)
passed-by-reference argument. */
for (t = DECL_ARGUMENTS (current_function_decl); t; t = DECL_CHAIN (t))
{
- varinfo_t p;
+ varinfo_t p = get_vi_for_tree (t);
/* For restrict qualified pointers to objects passed by
reference build a real representative for the pointed-to object.
@@ -5619,34 +5611,37 @@ intra_create_variable_infos (void)
DECL_EXTERNAL (heapvar) = 1;
vi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS");
insert_vi_for_tree (heapvar, vi);
- lhsc.var = get_vi_for_tree (t)->id;
+ lhsc.var = p->id;
lhsc.type = SCALAR;
lhsc.offset = 0;
rhsc.var = vi->id;
rhsc.type = ADDRESSOF;
rhsc.offset = 0;
process_constraint (new_constraint (lhsc, rhsc));
- vi->is_restrict_var = 1;
for (; vi; vi = vi->next)
if (vi->may_have_pointers)
{
if (vi->only_restrict_pointers)
- make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
- make_copy_constraint (vi, nonlocal_id);
+ make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ else
+ make_copy_constraint (vi, nonlocal_id);
}
continue;
}
- for (p = get_vi_for_tree (t); p; p = p->next)
- {
- if (p->may_have_pointers)
- make_constraint_from (p, nonlocal_id);
- if (p->only_restrict_pointers)
- make_constraint_from_restrict (p, "PARM_RESTRICT");
- }
if (POINTER_TYPE_P (TREE_TYPE (t))
&& TYPE_RESTRICT (TREE_TYPE (t)))
- make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT");
+ make_constraint_from_global_restrict (p, "PARM_RESTRICT");
+ else
+ {
+ for (; p; p = p->next)
+ {
+ if (p->only_restrict_pointers)
+ make_constraint_from_global_restrict (p, "PARM_RESTRICT");
+ else if (p->may_have_pointers)
+ make_constraint_from (p, nonlocal_id);
+ }
+ }
}
/* Add a constraint for a result decl that is passed by reference. */
@@ -5822,15 +5817,11 @@ find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt)
|| vi->id == integer_id)
pt->anything = 1;
}
- if (vi->is_restrict_var)
- pt->vars_contains_restrict = true;
}
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
- if (pt->anything
- && (orig_vi->is_artificial_var
- || !pt->vars_contains_restrict))
+ if (pt->anything)
return;
/* Share the final set of variables when possible. */
@@ -5921,13 +5912,11 @@ pt_solution_reset (struct pt_solution *pt)
it contains restrict tag variables. */
void
-pt_solution_set (struct pt_solution *pt, bitmap vars,
- bool vars_contains_global, bool vars_contains_restrict)
+pt_solution_set (struct pt_solution *pt, bitmap vars, bool vars_contains_global)
{
memset (pt, 0, sizeof (struct pt_solution));
pt->vars = vars;
pt->vars_contains_global = vars_contains_global;
- pt->vars_contains_restrict = vars_contains_restrict;
}
/* Set the points-to solution *PT to point only to the variable VAR. */
@@ -5962,7 +5951,6 @@ pt_solution_ior_into (struct pt_solution *dest, struct pt_solution *src)
dest->ipa_escaped |= src->ipa_escaped;
dest->null |= src->null;
dest->vars_contains_global |= src->vars_contains_global;
- dest->vars_contains_restrict |= src->vars_contains_restrict;
if (!src->vars)
return;
@@ -6150,27 +6138,6 @@ pt_solutions_intersect (struct pt_solution *pt1, struct pt_solution *pt2)
return res;
}
-/* Return true if both points-to solutions PT1 and PT2 for two restrict
- qualified pointers are possibly based on the same pointer. */
-
-bool
-pt_solutions_same_restrict_base (struct pt_solution *pt1,
- struct pt_solution *pt2)
-{
- /* If we deal with points-to solutions of two restrict qualified
- pointers solely rely on the pointed-to variable bitmap intersection.
- For two pointers that are based on each other the bitmaps will
- intersect. */
- if (pt1->vars_contains_restrict
- && pt2->vars_contains_restrict)
- {
- gcc_assert (pt1->vars && pt2->vars);
- return bitmap_intersect_p (pt1->vars, pt2->vars);
- }
-
- return true;
-}
-
/* Dump points-to information to OUTFILE. */
@@ -6583,7 +6550,6 @@ compute_points_to_sets (void)
/* Mark escaped HEAP variables as global. */
FOR_EACH_VEC_ELT (varinfo_t, varmap, i, vi)
if (vi->is_heap_var
- && !vi->is_restrict_var
&& !vi->is_global_var)
DECL_EXTERNAL (vi->decl) = vi->is_global_var
= pt_solution_includes (&cfun->gimple_df->escaped, vi->decl);
@@ -6803,7 +6769,7 @@ gate_ipa_pta (void)
/* IPA PTA solutions for ESCAPED. */
struct pt_solution ipa_escaped_pt
- = { true, false, false, false, false, false, false, NULL };
+ = { true, false, false, false, false, false, NULL };
/* Associate node with varinfo DATA. Worker for
cgraph_for_node_and_aliases. */
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 611a30f23a4..2a47dc6b0a9 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -773,18 +773,56 @@ same_succ_flush_bbs (bitmap bbs)
}
}
+/* Release the last vdef in BB, either normal or phi result. */
+
+static void
+release_last_vdef (basic_block bb)
+{
+ gimple_stmt_iterator i;
+
+ for (i = gsi_last_bb (bb); !gsi_end_p (i); gsi_prev_nondebug (&i))
+ {
+ gimple stmt = gsi_stmt (i);
+ if (gimple_vdef (stmt) == NULL_TREE)
+ continue;
+
+ mark_virtual_operand_for_renaming (gimple_vdef (stmt));
+ return;
+ }
+
+ for (i = gsi_start_phis (bb); !gsi_end_p (i); gsi_next (&i))
+ {
+ gimple phi = gsi_stmt (i);
+ tree res = gimple_phi_result (phi);
+
+ if (is_gimple_reg (res))
+ continue;
+
+ mark_virtual_phi_result_for_renaming (phi);
+ return;
+ }
+
+}
+
/* Delete all deleted_bbs. */
static void
-purge_bbs (void)
+purge_bbs (bool update_vops)
{
unsigned int i;
bitmap_iterator bi;
+ basic_block bb;
same_succ_flush_bbs (deleted_bbs);
EXECUTE_IF_SET_IN_BITMAP (deleted_bbs, 0, i, bi)
- delete_basic_block (BASIC_BLOCK (i));
+ {
+ bb = BASIC_BLOCK (i);
+ if (!update_vops)
+ release_last_vdef (bb);
+
+ delete_basic_block (bb);
+ }
bitmap_and_compl_into (deleted_bb_preds, deleted_bbs);
bitmap_clear (deleted_bbs);
@@ -1470,11 +1508,14 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
edge e;
edge_iterator ei;
+ phi_vuse2 = vop_at_entry (bb2);
+ if (phi_vuse2 != NULL_TREE && TREE_CODE (phi_vuse2) != SSA_NAME)
+ phi_vuse2 = NULL_TREE;
+
if (update_vops)
{
/* Find the vops at entry of bb1 and bb2. */
phi_vuse1 = vop_at_entry (bb1);
- phi_vuse2 = vop_at_entry (bb2);
/* If one of the 2 not found, it means there's no need to update. */
update_vops = phi_vuse1 != NULL_TREE && phi_vuse2 != NULL_TREE;
@@ -1507,6 +1548,9 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
gcc_assert (pred_edge != NULL);
if (update_vops)
VEC_safe_push (edge, heap, redirected_edges, pred_edge);
+ else if (phi_vuse2 && gimple_bb (SSA_NAME_DEF_STMT (phi_vuse2)) == bb2)
+ add_phi_arg (SSA_NAME_DEF_STMT (phi_vuse2), SSA_NAME_VAR (phi_vuse2),
+ pred_edge, UNKNOWN_LOCATION);
}
/* Update the vops. */
@@ -1665,7 +1709,7 @@ tail_merge_optimize (unsigned int todo)
break;
free_dominance_info (CDI_DOMINATORS);
- purge_bbs ();
+ purge_bbs (update_vops);
if (iteration_nr == max_iterations)
break;
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index a0115938077..8f73d9176f2 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1270,12 +1270,6 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
!= TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
return false;
- /* Do not lose casts to restrict qualified pointers. */
- if ((TYPE_RESTRICT (outer_type)
- != TYPE_RESTRICT (inner_type))
- && TYPE_RESTRICT (outer_type))
- return false;
-
/* If the outer type is (void *), the conversion is not necessary. */
if (VOID_TYPE_P (TREE_TYPE (outer_type)))
return true;
@@ -1969,6 +1963,8 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs)
a non-register. Otherwise we are confused and forget to
add virtual operands for it. */
&& (!is_gimple_reg_type (TREE_TYPE (var))
+ || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
+ || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
|| !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
{
TREE_ADDRESSABLE (var) = 0;
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 0a79a249151..db2bb376432 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -1049,7 +1049,7 @@ streamer_get_builtin_tree (struct lto_input_block *ib, struct data_in *data_in)
{
if (fcode >= END_BUILTINS)
fatal_error ("machine independent builtin code out of range");
- result = built_in_decls[fcode];
+ result = builtin_decl_explicit (fcode);
gcc_assert (result);
}
else if (fclass == BUILT_IN_MD)
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 042d703e15f..37ff807b1b5 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "flags.h"
#include "ggc.h"
+#include "diagnostic.h"
/* Need to include rtl.h, expr.h, etc. for optabs. */
#include "expr.h"
@@ -129,7 +130,6 @@ do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
return gimplify_build2 (gsi, code, inner_type, a, b);
}
-
/* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
INNER_TYPE is the type of A and B elements
@@ -235,6 +235,14 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
int delta = tree_low_cst (part_width, 1)
/ tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
int i;
+ location_t loc = gimple_location (gsi_stmt (*gsi));
+
+ if (types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
+ warning_at (loc, OPT_Wvector_operation_performance,
+ "vector operation will be expanded piecewise");
+ else
+ warning_at (loc, OPT_Wvector_operation_performance,
+ "vector operation will be expanded in parallel");
v = VEC_alloc(constructor_elt, gc, (nunits + delta - 1) / delta);
for (i = 0; i < nunits;
@@ -260,6 +268,7 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
tree result, compute_type;
enum machine_mode mode;
int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
+ location_t loc = gimple_location (gsi_stmt (*gsi));
/* We have three strategies. If the type is already correct, just do
the operation an element at a time. Else, if the vector is wider than
@@ -284,6 +293,9 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0);
compute_type = lang_hooks.types.type_for_mode (mode, 1);
result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
+ warning_at (loc, OPT_Wvector_operation_performance,
+ "vector operation will be expanded with a "
+ "single scalar operation");
}
return result;
@@ -355,10 +367,10 @@ uniform_vector_p (tree vec)
}
if (i != TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)))
return NULL_TREE;
-
+
return first;
}
-
+
return NULL_TREE;
}
@@ -400,8 +412,8 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
case PLUS_EXPR:
case MINUS_EXPR:
if (!TYPE_OVERFLOW_TRAPS (type))
- return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
- gimple_assign_rhs1 (assign),
+ return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
+ gimple_assign_rhs1 (assign),
gimple_assign_rhs2 (assign), code);
break;
@@ -498,6 +510,214 @@ type_for_widest_vector_mode (enum machine_mode inner_mode, optab op, int satp)
}
}
+
+/* Build a reference to the element of the vector VECT. Function
+ returns either the element itself, either BIT_FIELD_REF, or an
+ ARRAY_REF expression.
+
+ GSI is requred to insert temporary variables while building a
+ refernece to the element of the vector VECT.
+
+ PTMPVEC is a pointer to the temporary variable for caching
+ purposes. In case when PTMPVEC is NULL new temporary variable
+ will be created. */
+static tree
+vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
+{
+ tree vect_type, vect_elt_type;
+ gimple asgn;
+ tree tmpvec;
+ tree arraytype;
+ bool need_asgn = true;
+ unsigned int elements;
+
+ vect_type = TREE_TYPE (vect);
+ vect_elt_type = TREE_TYPE (vect_type);
+ elements = TYPE_VECTOR_SUBPARTS (vect_type);
+
+ if (TREE_CODE (idx) == INTEGER_CST)
+ {
+ unsigned HOST_WIDE_INT index;
+
+ /* Given that we're about to compute a binary modulus,
+ we don't care about the high bits of the value. */
+ index = TREE_INT_CST_LOW (idx);
+ if (!host_integerp (idx, 1) || index >= elements)
+ {
+ index &= elements - 1;
+ idx = build_int_cst (TREE_TYPE (idx), index);
+ }
+
+ /* When lowering a vector statement sequence do some easy
+ simplification by looking through intermediate vector results. */
+ if (TREE_CODE (vect) == SSA_NAME)
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (vect);
+ if (is_gimple_assign (def_stmt)
+ && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
+ || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
+ vect = gimple_assign_rhs1 (def_stmt);
+ }
+
+ if (TREE_CODE (vect) == VECTOR_CST)
+ {
+ unsigned i;
+ tree vals = TREE_VECTOR_CST_ELTS (vect);
+ for (i = 0; vals; vals = TREE_CHAIN (vals), ++i)
+ if (i == index)
+ return TREE_VALUE (vals);
+ return build_zero_cst (vect_elt_type);
+ }
+ else if (TREE_CODE (vect) == CONSTRUCTOR)
+ {
+ unsigned i;
+ tree elt_i, elt_v;
+
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (vect), i, elt_i, elt_v)
+ if (operand_equal_p (elt_i, idx, 0))
+ return elt_v;
+ return build_zero_cst (vect_elt_type);
+ }
+ else
+ {
+ tree size = TYPE_SIZE (vect_elt_type);
+ tree pos = fold_build2 (MULT_EXPR, TREE_TYPE (idx), idx, size);
+ return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
+ }
+ }
+
+ if (!ptmpvec)
+ tmpvec = create_tmp_var (vect_type, "vectmp");
+ else if (!*ptmpvec)
+ tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
+ else
+ {
+ tmpvec = *ptmpvec;
+ need_asgn = false;
+ }
+
+ if (need_asgn)
+ {
+ TREE_ADDRESSABLE (tmpvec) = 1;
+ asgn = gimple_build_assign (tmpvec, vect);
+ gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
+ }
+
+ arraytype = build_array_type_nelts (vect_elt_type, elements);
+ return build4 (ARRAY_REF, vect_elt_type,
+ build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
+ idx, NULL_TREE, NULL_TREE);
+}
+
+/* Check if VEC_PERM_EXPR within the given setting is supported
+ by hardware, or lower it piecewise.
+
+ When VEC_PERM_EXPR has the same first and second operands:
+ VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
+ {v0[mask[0]], v0[mask[1]], ...}
+ MASK and V0 must have the same number of elements.
+
+ Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
+ {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
+ V0 and V1 must have the same type. MASK, V0, V1 must have the
+ same number of arguments. */
+
+static void
+lower_vec_perm (gimple_stmt_iterator *gsi)
+{
+ gimple stmt = gsi_stmt (*gsi);
+ tree mask = gimple_assign_rhs3 (stmt);
+ tree vec0 = gimple_assign_rhs1 (stmt);
+ tree vec1 = gimple_assign_rhs2 (stmt);
+ tree vect_type = TREE_TYPE (vec0);
+ tree mask_type = TREE_TYPE (mask);
+ tree vect_elt_type = TREE_TYPE (vect_type);
+ tree mask_elt_type = TREE_TYPE (mask_type);
+ unsigned int elements = TYPE_VECTOR_SUBPARTS (vect_type);
+ VEC(constructor_elt,gc) *v;
+ tree constr, t, si, i_val;
+ tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
+ bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
+ location_t loc = gimple_location (gsi_stmt (*gsi));
+ unsigned i;
+
+ if (can_vec_perm_expr_p (vect_type, mask))
+ return;
+
+ warning_at (loc, OPT_Wvector_operation_performance,
+ "vector shuffling operation will be expanded piecewise");
+
+
+ v = VEC_alloc (constructor_elt, gc, elements);
+ for (i = 0; i < elements; i++)
+ {
+ si = size_int (i);
+ i_val = vector_element (gsi, mask, si, &masktmp);
+
+ if (TREE_CODE (i_val) == INTEGER_CST)
+ {
+ unsigned HOST_WIDE_INT index;
+
+ index = TREE_INT_CST_LOW (i_val);
+ if (!host_integerp (i_val, 1) || index >= elements)
+ i_val = build_int_cst (mask_elt_type, index & (elements - 1));
+
+ if (two_operand_p && (index & elements) != 0)
+ t = vector_element (gsi, vec1, i_val, &vec1tmp);
+ else
+ t = vector_element (gsi, vec0, i_val, &vec0tmp);
+
+ t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ }
+ else
+ {
+ tree cond = NULL_TREE, v0_val;
+
+ if (two_operand_p)
+ {
+ cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
+ build_int_cst (mask_elt_type, elements));
+ cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ }
+
+ i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
+ build_int_cst (mask_elt_type, elements - 1));
+ i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+
+ v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
+ v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+
+ if (two_operand_p)
+ {
+ tree v1_val;
+
+ v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
+ v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+
+ cond = fold_build2 (EQ_EXPR, boolean_type_node,
+ cond, build_zero_cst (mask_elt_type));
+ cond = fold_build3 (COND_EXPR, vect_elt_type,
+ cond, v0_val, v1_val);
+ t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ }
+ else
+ t = v0_val;
+ }
+
+ CONSTRUCTOR_APPEND_ELT (v, si, t);
+ }
+
+ constr = build_constructor (vect_type, v);
+ gimple_assign_set_rhs_from_tree (gsi, constr);
+ update_stmt (gsi_stmt (*gsi));
+}
+
/* Process one statement. If we identify a vector operation, expand it. */
static void
@@ -518,6 +738,12 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
rhs_class = get_gimple_rhs_class (code);
lhs = gimple_assign_lhs (stmt);
+ if (code == VEC_PERM_EXPR)
+ {
+ lower_vec_perm (gsi);
+ return;
+ }
+
if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
return;
@@ -549,60 +775,39 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == LROTATE_EXPR
|| code == RROTATE_EXPR)
{
- bool vector_scalar_shift;
- op = optab_for_tree_code (code, type, optab_scalar);
-
- /* Vector/Scalar shift is supported. */
- vector_scalar_shift = (op && (optab_handler (op, TYPE_MODE (type))
- != CODE_FOR_nothing));
-
- /* If the 2nd argument is vector, we need a vector/vector shift.
- Except all the elements in the second vector are the same. */
+ /* Check whether we have vector <op> {x,x,x,x} where x
+ could be a scalar variable or a constant. Transform
+ vector <op> {x,x,x,x} ==> vector <op> scalar. */
if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
{
tree first;
gimple def_stmt;
- /* Check whether we have vector <op> {x,x,x,x} where x
- could be a scalar variable or a constant. Transform
- vector <op> {x,x,x,x} ==> vector <op> scalar. */
- if (vector_scalar_shift
- && ((TREE_CODE (rhs2) == VECTOR_CST
- && (first = uniform_vector_p (rhs2)) != NULL_TREE)
- || (TREE_CODE (rhs2) == SSA_NAME
- && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
- && gimple_assign_single_p (def_stmt)
- && (first = uniform_vector_p
- (gimple_assign_rhs1 (def_stmt))) != NULL_TREE)))
+ if ((TREE_CODE (rhs2) == VECTOR_CST
+ && (first = uniform_vector_p (rhs2)) != NULL_TREE)
+ || (TREE_CODE (rhs2) == SSA_NAME
+ && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+ && gimple_assign_single_p (def_stmt)
+ && (first = uniform_vector_p
+ (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))
{
gimple_assign_set_rhs2 (stmt, first);
update_stmt (stmt);
rhs2 = first;
}
- else
- op = optab_for_tree_code (code, type, optab_vector);
}
-
- /* Try for a vector/scalar shift, and if we don't have one, see if we
- have a vector/vector shift */
- else if (!vector_scalar_shift)
+
+ if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
+ op = optab_for_tree_code (code, type, optab_vector);
+ else
{
- op = optab_for_tree_code (code, type, optab_vector);
+ op = optab_for_tree_code (code, type, optab_scalar);
- if (op && (optab_handler (op, TYPE_MODE (type))
- != CODE_FOR_nothing))
- {
- /* Transform vector <op> scalar => vector <op> {x,x,x,x}. */
- int n_parts = TYPE_VECTOR_SUBPARTS (type);
- int part_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
- tree part_type = lang_hooks.types.type_for_size (part_size, 1);
- tree vect_type = build_vector_type (part_type, n_parts);
-
- rhs2 = fold_convert (part_type, rhs2);
- rhs2 = build_vector_from_val (vect_type, rhs2);
- gimple_assign_set_rhs2 (stmt, rhs2);
- update_stmt (stmt);
- }
+ /* The rtl expander will expand vector/scalar as vector/vector
+ if necessary. Don't bother converting the stmt here. */
+ if (op == NULL
+ || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+ op = optab_for_tree_code (code, type, optab_vector);
}
}
else
@@ -618,7 +823,9 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == VEC_UNPACK_LO_EXPR
|| code == VEC_PACK_TRUNC_EXPR
|| code == VEC_PACK_SAT_EXPR
- || code == VEC_PACK_FIX_TRUNC_EXPR)
+ || code == VEC_PACK_FIX_TRUNC_EXPR
+ || code == VEC_WIDEN_LSHIFT_HI_EXPR
+ || code == VEC_WIDEN_LSHIFT_LO_EXPR)
type = TREE_TYPE (rhs1);
/* Optabs will try converting a negation into a subtraction, so
@@ -648,12 +855,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
if (compute_type == type)
{
compute_mode = TYPE_MODE (compute_type);
- if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FRACT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UFRACT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_ACCUM
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UACCUM)
+ if (VECTOR_MODE_P (compute_mode)
&& op != NULL
&& optab_handler (op, compute_mode) != CODE_FOR_nothing)
return;
@@ -684,9 +886,9 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
if it may need the bit-twiddling tricks implemented in this file. */
static bool
-gate_expand_vector_operations (void)
+gate_expand_vector_operations_ssa (void)
{
- return flag_tree_vectorize != 0;
+ return optimize == 0;
}
static unsigned int
@@ -719,7 +921,7 @@ struct gimple_opt_pass pass_lower_vector =
{
GIMPLE_PASS,
"veclower", /* name */
- 0, /* gate */
+ gate_expand_vector_operations_ssa, /* gate */
expand_vector_operations, /* execute */
NULL, /* sub */
NULL, /* next */
@@ -732,6 +934,7 @@ struct gimple_opt_pass pass_lower_vector =
TODO_update_ssa /* todo_flags_finish */
| TODO_verify_ssa
| TODO_verify_stmts | TODO_verify_flow
+ | TODO_cleanup_cfg
}
};
@@ -740,7 +943,7 @@ struct gimple_opt_pass pass_lower_vector_ssa =
{
GIMPLE_PASS,
"veclower2", /* name */
- gate_expand_vector_operations, /* gate */
+ 0, /* gate */
expand_vector_operations, /* execute */
NULL, /* sub */
NULL, /* next */
@@ -753,6 +956,7 @@ struct gimple_opt_pass pass_lower_vector_ssa =
TODO_update_ssa /* todo_flags_finish */
| TODO_verify_ssa
| TODO_verify_stmts | TODO_verify_flow
+ | TODO_cleanup_cfg
}
};
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 7fc107cafa9..94ab9b79667 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -49,13 +49,20 @@ static gimple vect_recog_dot_prod_pattern (VEC (gimple, heap) **, tree *,
static gimple vect_recog_pow_pattern (VEC (gimple, heap) **, tree *, tree *);
static gimple vect_recog_over_widening_pattern (VEC (gimple, heap) **, tree *,
tree *);
+static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **,
+ tree *, tree *);
+static gimple vect_recog_mixed_size_cond_pattern (VEC (gimple, heap) **,
+ tree *, tree *);
+static gimple vect_recog_bool_pattern (VEC (gimple, heap) **, tree *, tree *);
static vect_recog_func_ptr vect_vect_recog_func_ptrs[NUM_PATTERNS] = {
vect_recog_widen_mult_pattern,
vect_recog_widen_sum_pattern,
vect_recog_dot_prod_pattern,
vect_recog_pow_pattern,
- vect_recog_over_widening_pattern};
-
+ vect_recog_over_widening_pattern,
+ vect_recog_widen_shift_pattern,
+ vect_recog_mixed_size_cond_pattern,
+ vect_recog_bool_pattern};
/* Function widened_name_p
@@ -335,27 +342,37 @@ vect_recog_dot_prod_pattern (VEC (gimple, heap) **stmts, tree *type_in,
}
-/* Handle two cases of multiplication by a constant. The first one is when
- the constant, CONST_OPRND, fits the type (HALF_TYPE) of the second
- operand (OPRND). In that case, we can peform widen-mult from HALF_TYPE to
- TYPE.
+/* Handle widening operation by a constant. At the moment we support MULT_EXPR
+ and LSHIFT_EXPR.
+
+ For MULT_EXPR we check that CONST_OPRND fits HALF_TYPE, and for LSHIFT_EXPR
+ we check that CONST_OPRND is less or equal to the size of HALF_TYPE.
Otherwise, if the type of the result (TYPE) is at least 4 times bigger than
- HALF_TYPE, and CONST_OPRND fits an intermediate type (2 times smaller than
- TYPE), we can perform widen-mult from the intermediate type to TYPE and
- replace a_T = (TYPE) a_t; with a_it - (interm_type) a_t; */
+ HALF_TYPE, and there is an intermediate type (2 times smaller than TYPE)
+ that satisfies the above restrictions, we can perform a widening opeartion
+ from the intermediate type to TYPE and replace a_T = (TYPE) a_t;
+ with a_it = (interm_type) a_t; */
static bool
-vect_handle_widen_mult_by_const (gimple stmt, tree const_oprnd, tree *oprnd,
- VEC (gimple, heap) **stmts, tree type,
- tree *half_type, gimple def_stmt)
+vect_handle_widen_op_by_const (gimple stmt, enum tree_code code,
+ tree const_oprnd, tree *oprnd,
+ VEC (gimple, heap) **stmts, tree type,
+ tree *half_type, gimple def_stmt)
{
tree new_type, new_oprnd, tmp;
gimple new_stmt;
loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (vinfo_for_stmt (stmt));
struct loop *loop = LOOP_VINFO_LOOP (loop_info);
- if (int_fits_type_p (const_oprnd, *half_type))
+ if (code != MULT_EXPR && code != LSHIFT_EXPR)
+ return false;
+
+ if (((code == MULT_EXPR && int_fits_type_p (const_oprnd, *half_type))
+ || (code == LSHIFT_EXPR
+ && compare_tree_int (const_oprnd, TYPE_PRECISION (*half_type))
+ != 1))
+ && TYPE_PRECISION (type) == (TYPE_PRECISION (*half_type) * 2))
{
/* CONST_OPRND is a constant of HALF_TYPE. */
*oprnd = gimple_assign_rhs1 (def_stmt);
@@ -368,14 +385,16 @@ vect_handle_widen_mult_by_const (gimple stmt, tree const_oprnd, tree *oprnd,
|| !vinfo_for_stmt (def_stmt))
return false;
- /* TYPE is 4 times bigger than HALF_TYPE, try widen-mult for
+ /* TYPE is 4 times bigger than HALF_TYPE, try widening operation for
a type 2 times bigger than HALF_TYPE. */
new_type = build_nonstandard_integer_type (TYPE_PRECISION (type) / 2,
TYPE_UNSIGNED (type));
- if (!int_fits_type_p (const_oprnd, new_type))
+ if ((code == MULT_EXPR && !int_fits_type_p (const_oprnd, new_type))
+ || (code == LSHIFT_EXPR
+ && compare_tree_int (const_oprnd, TYPE_PRECISION (new_type)) == 1))
return false;
- /* Use NEW_TYPE for widen_mult. */
+ /* Use NEW_TYPE for widening operation. */
if (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)))
{
new_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt));
@@ -385,6 +404,7 @@ vect_handle_widen_mult_by_const (gimple stmt, tree const_oprnd, tree *oprnd,
|| TREE_TYPE (gimple_assign_lhs (new_stmt)) != new_type)
return false;
+ VEC_safe_push (gimple, heap, *stmts, def_stmt);
*oprnd = gimple_assign_lhs (new_stmt);
}
else
@@ -396,7 +416,6 @@ vect_handle_widen_mult_by_const (gimple stmt, tree const_oprnd, tree *oprnd,
new_oprnd = make_ssa_name (tmp, NULL);
new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, *oprnd,
NULL_TREE);
- SSA_NAME_DEF_STMT (new_oprnd) = new_stmt;
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)) = new_stmt;
VEC_safe_push (gimple, heap, *stmts, def_stmt);
*oprnd = new_oprnd;
@@ -495,7 +514,7 @@ vect_recog_widen_mult_pattern (VEC (gimple, heap) **stmts,
enum tree_code dummy_code;
int dummy_int;
VEC (tree, heap) *dummy_vec;
- bool op0_ok, op1_ok;
+ bool op1_ok;
if (!is_gimple_assign (last_stmt))
return NULL;
@@ -515,38 +534,23 @@ vect_recog_widen_mult_pattern (VEC (gimple, heap) **stmts,
return NULL;
/* Check argument 0. */
- op0_ok = widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false);
+ if (!widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false))
+ return NULL;
/* Check argument 1. */
op1_ok = widened_name_p (oprnd1, last_stmt, &half_type1, &def_stmt1, false);
- /* In case of multiplication by a constant one of the operands may not match
- the pattern, but not both. */
- if (!op0_ok && !op1_ok)
- return NULL;
-
- if (op0_ok && op1_ok)
+ if (op1_ok)
{
oprnd0 = gimple_assign_rhs1 (def_stmt0);
oprnd1 = gimple_assign_rhs1 (def_stmt1);
}
- else if (!op0_ok)
- {
- if (TREE_CODE (oprnd0) == INTEGER_CST
- && TREE_CODE (half_type1) == INTEGER_TYPE
- && vect_handle_widen_mult_by_const (last_stmt, oprnd0, &oprnd1,
- stmts, type,
- &half_type1, def_stmt1))
- half_type0 = half_type1;
- else
- return NULL;
- }
- else if (!op1_ok)
+ else
{
if (TREE_CODE (oprnd1) == INTEGER_CST
&& TREE_CODE (half_type0) == INTEGER_TYPE
- && vect_handle_widen_mult_by_const (last_stmt, oprnd1, &oprnd0,
- stmts, type,
- &half_type0, def_stmt0))
+ && vect_handle_widen_op_by_const (last_stmt, MULT_EXPR, oprnd1,
+ &oprnd0, stmts, type,
+ &half_type0, def_stmt0))
half_type1 = half_type0;
else
return NULL;
@@ -615,7 +619,6 @@ vect_recog_widen_mult_pattern (VEC (gimple, heap) **stmts,
var = vect_recog_temp_ssa_var (type, NULL);
pattern_stmt = gimple_build_assign_with_ops (WIDEN_MULT_EXPR, var, oprnd0,
oprnd1);
- SSA_NAME_DEF_STMT (var) = pattern_stmt;
if (vect_print_dump_info (REPORT_DETAILS))
print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
@@ -699,7 +702,6 @@ vect_recog_pow_pattern (VEC (gimple, heap) **stmts, tree *type_in,
var = vect_recog_temp_ssa_var (TREE_TYPE (base), NULL);
stmt = gimple_build_assign_with_ops (MULT_EXPR, var, base, base);
- SSA_NAME_DEF_STMT (var) = stmt;
return stmt;
}
@@ -822,7 +824,6 @@ vect_recog_widen_sum_pattern (VEC (gimple, heap) **stmts, tree *type_in,
var = vect_recog_temp_ssa_var (type, NULL);
pattern_stmt = gimple_build_assign_with_ops (WIDEN_SUM_EXPR, var,
oprnd0, oprnd1);
- SSA_NAME_DEF_STMT (var) = pattern_stmt;
if (vect_print_dump_info (REPORT_DETAILS))
{
@@ -1001,6 +1002,7 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type,
|| TREE_TYPE (gimple_assign_lhs (new_stmt)) != interm_type)
return false;
+ VEC_safe_push (gimple, heap, *stmts, def_stmt);
oprnd = gimple_assign_lhs (new_stmt);
}
else
@@ -1012,7 +1014,6 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type,
new_oprnd = make_ssa_name (tmp, NULL);
new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd,
oprnd, NULL_TREE);
- SSA_NAME_DEF_STMT (new_oprnd) = new_stmt;
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)) = new_stmt;
VEC_safe_push (gimple, heap, *stmts, def_stmt);
oprnd = new_oprnd;
@@ -1034,7 +1035,6 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type,
new_oprnd = make_ssa_name (tmp, NULL);
new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd,
oprnd, NULL_TREE);
- SSA_NAME_DEF_STMT (new_oprnd) = new_stmt;
oprnd = new_oprnd;
*new_def_stmt = new_stmt;
}
@@ -1070,10 +1070,8 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type,
constants.
Check if S3 and S4 can be done on a smaller type than 'TYPE', it can either
be 'type' or some intermediate type. For now, we expect S5 to be a type
- demotion operation. We also check that S3 and S4 have only one use.
-.
+ demotion operation. We also check that S3 and S4 have only one use. */
-*/
static gimple
vect_recog_over_widening_pattern (VEC (gimple, heap) **stmts,
tree *type_in, tree *type_out)
@@ -1131,15 +1129,15 @@ vect_recog_over_widening_pattern (VEC (gimple, heap) **stmts,
statetments, except for the case when the last statement in the
sequence doesn't have a corresponding pattern statement. In such
case we associate the last pattern statement with the last statement
- in the sequence. Therefore, we only add an original statetement to
+ in the sequence. Therefore, we only add the original statement to
the list if we know that it is not the last. */
if (prev_stmt)
VEC_safe_push (gimple, heap, *stmts, prev_stmt);
var = vect_recog_temp_ssa_var (new_type, NULL);
- pattern_stmt = gimple_build_assign_with_ops (
- gimple_assign_rhs_code (stmt), var, op0, op1);
- SSA_NAME_DEF_STMT (var) = pattern_stmt;
+ pattern_stmt
+ = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), var,
+ op0, op1);
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt)) = pattern_stmt;
STMT_VINFO_PATTERN_DEF_STMT (vinfo_for_stmt (stmt)) = new_def_stmt;
@@ -1178,7 +1176,6 @@ vect_recog_over_widening_pattern (VEC (gimple, heap) **stmts,
new_oprnd = make_ssa_name (tmp, NULL);
pattern_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd,
var, NULL_TREE);
- SSA_NAME_DEF_STMT (new_oprnd) = pattern_stmt;
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt)) = pattern_stmt;
*type_in = get_vectype_for_scalar_type (new_type);
@@ -1217,6 +1214,729 @@ vect_recog_over_widening_pattern (VEC (gimple, heap) **stmts,
return pattern_stmt;
}
+/* Detect widening shift pattern:
+
+ type a_t;
+ TYPE a_T, res_T;
+
+ S1 a_t = ;
+ S2 a_T = (TYPE) a_t;
+ S3 res_T = a_T << CONST;
+
+ where type 'TYPE' is at least double the size of type 'type'.
+
+ Also detect unsgigned cases:
+
+ unsigned type a_t;
+ unsigned TYPE u_res_T;
+ TYPE a_T, res_T;
+
+ S1 a_t = ;
+ S2 a_T = (TYPE) a_t;
+ S3 res_T = a_T << CONST;
+ S4 u_res_T = (unsigned TYPE) res_T;
+
+ And a case when 'TYPE' is 4 times bigger than 'type'. In that case we
+ create an additional pattern stmt for S2 to create a variable of an
+ intermediate type, and perform widen-shift on the intermediate type:
+
+ type a_t;
+ interm_type a_it;
+ TYPE a_T, res_T, res_T';
+
+ S1 a_t = ;
+ S2 a_T = (TYPE) a_t;
+ '--> a_it = (interm_type) a_t;
+ S3 res_T = a_T << CONST;
+ '--> res_T' = a_it <<* CONST;
+
+ Input/Output:
+
+ * STMTS: Contains a stmt from which the pattern search begins.
+ In case of unsigned widen-shift, the original stmt (S3) is replaced with S4
+ in STMTS. When an intermediate type is used and a pattern statement is
+ created for S2, we also put S2 here (before S3).
+
+ Output:
+
+ * TYPE_IN: The type of the input arguments to the pattern.
+
+ * TYPE_OUT: The type of the output of this pattern.
+
+ * Return value: A new stmt that will be used to replace the sequence of
+ stmts that constitute the pattern. In this case it will be:
+ WIDEN_LSHIFT_EXPR <a_t, CONST>. */
+
+static gimple
+vect_recog_widen_shift_pattern (VEC (gimple, heap) **stmts,
+ tree *type_in, tree *type_out)
+{
+ gimple last_stmt = VEC_pop (gimple, *stmts);
+ gimple def_stmt0;
+ tree oprnd0, oprnd1;
+ tree type, half_type0;
+ gimple pattern_stmt, orig_stmt = NULL;
+ tree vectype, vectype_out = NULL_TREE;
+ tree dummy;
+ tree var;
+ enum tree_code dummy_code;
+ int dummy_int;
+ VEC (tree, heap) * dummy_vec;
+ gimple use_stmt = NULL;
+ bool over_widen = false;
+
+ if (!is_gimple_assign (last_stmt) || !vinfo_for_stmt (last_stmt))
+ return NULL;
+
+ orig_stmt = last_stmt;
+ if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt)))
+ {
+ /* This statement was also detected as over-widening operation (it can't
+ be any other pattern, because only over-widening detects shifts).
+ LAST_STMT is the final type demotion statement, but its related
+ statement is shift. We analyze the related statement to catch cases:
+
+ orig code:
+ type a_t;
+ itype res;
+ TYPE a_T, res_T;
+
+ S1 a_T = (TYPE) a_t;
+ S2 res_T = a_T << CONST;
+ S3 res = (itype)res_T;
+
+ (size of type * 2 <= size of itype
+ and size of itype * 2 <= size of TYPE)
+
+ code after over-widening pattern detection:
+
+ S1 a_T = (TYPE) a_t;
+ --> a_it = (itype) a_t;
+ S2 res_T = a_T << CONST;
+ S3 res = (itype)res_T; <--- LAST_STMT
+ --> res = a_it << CONST;
+
+ after widen_shift:
+
+ S1 a_T = (TYPE) a_t;
+ --> a_it = (itype) a_t; - redundant
+ S2 res_T = a_T << CONST;
+ S3 res = (itype)res_T;
+ --> res = a_t w<< CONST;
+
+ i.e., we replace the three statements with res = a_t w<< CONST. */
+ last_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (last_stmt));
+ over_widen = true;
+ }
+
+ if (gimple_assign_rhs_code (last_stmt) != LSHIFT_EXPR)
+ return NULL;
+
+ oprnd0 = gimple_assign_rhs1 (last_stmt);
+ oprnd1 = gimple_assign_rhs2 (last_stmt);
+ if (TREE_CODE (oprnd0) != SSA_NAME || TREE_CODE (oprnd1) != INTEGER_CST)
+ return NULL;
+
+ /* Check operand 0: it has to be defined by a type promotion. */
+ if (!widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false))
+ return NULL;
+
+ /* Check operand 1: has to be positive. We check that it fits the type
+ in vect_handle_widen_op_by_const (). */
+ if (tree_int_cst_compare (oprnd1, size_zero_node) <= 0)
+ return NULL;
+
+ oprnd0 = gimple_assign_rhs1 (def_stmt0);
+ type = gimple_expr_type (last_stmt);
+
+ /* Check if this a widening operation. */
+ if (!vect_handle_widen_op_by_const (last_stmt, LSHIFT_EXPR, oprnd1,
+ &oprnd0, stmts,
+ type, &half_type0, def_stmt0))
+ return NULL;
+
+ /* Handle unsigned case. Look for
+ S4 u_res_T = (unsigned TYPE) res_T;
+ Use unsigned TYPE as the type for WIDEN_LSHIFT_EXPR. */
+ if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (half_type0))
+ {
+ tree lhs = gimple_assign_lhs (last_stmt), use_lhs;
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+ int nuses = 0;
+ tree use_type;
+
+ if (over_widen)
+ {
+ /* In case of over-widening pattern, S4 should be ORIG_STMT itself.
+ We check here that TYPE is the correct type for the operation,
+ i.e., it's the type of the original result. */
+ tree orig_type = gimple_expr_type (orig_stmt);
+ if ((TYPE_UNSIGNED (type) != TYPE_UNSIGNED (orig_type))
+ || (TYPE_PRECISION (type) != TYPE_PRECISION (orig_type)))
+ return NULL;
+ }
+ else
+ {
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
+ {
+ if (is_gimple_debug (USE_STMT (use_p)))
+ continue;
+ use_stmt = USE_STMT (use_p);
+ nuses++;
+ }
+
+ if (nuses != 1 || !is_gimple_assign (use_stmt)
+ || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
+ return NULL;
+
+ use_lhs = gimple_assign_lhs (use_stmt);
+ use_type = TREE_TYPE (use_lhs);
+
+ if (!INTEGRAL_TYPE_P (use_type)
+ || (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (use_type))
+ || (TYPE_PRECISION (type) != TYPE_PRECISION (use_type)))
+ return NULL;
+
+ type = use_type;
+ }
+ }
+
+ /* Pattern detected. */
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "vect_recog_widen_shift_pattern: detected: ");
+
+ /* Check target support. */
+ vectype = get_vectype_for_scalar_type (half_type0);
+ vectype_out = get_vectype_for_scalar_type (type);
+
+ if (!vectype
+ || !vectype_out
+ || !supportable_widening_operation (WIDEN_LSHIFT_EXPR, last_stmt,
+ vectype_out, vectype,
+ &dummy, &dummy, &dummy_code,
+ &dummy_code, &dummy_int,
+ &dummy_vec))
+ return NULL;
+
+ *type_in = vectype;
+ *type_out = vectype_out;
+
+ /* Pattern supported. Create a stmt to be used to replace the pattern. */
+ var = vect_recog_temp_ssa_var (type, NULL);
+ pattern_stmt =
+ gimple_build_assign_with_ops (WIDEN_LSHIFT_EXPR, var, oprnd0, oprnd1);
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
+
+ if (use_stmt)
+ last_stmt = use_stmt;
+ else
+ last_stmt = orig_stmt;
+
+ VEC_safe_push (gimple, heap, *stmts, last_stmt);
+ return pattern_stmt;
+}
+
+/* Function vect_recog_mixed_size_cond_pattern
+
+ Try to find the following pattern:
+
+ type x_t, y_t;
+ TYPE a_T, b_T, c_T;
+ loop:
+ S1 a_T = x_t CMP y_t ? b_T : c_T;
+
+ where type 'TYPE' is an integral type which has different size
+ from 'type'. b_T and c_T are constants and if 'TYPE' is wider
+ than 'type', the constants need to fit into an integer type
+ with the same width as 'type'.
+
+ Input:
+
+ * LAST_STMT: A stmt from which the pattern search begins.
+
+ Output:
+
+ * TYPE_IN: The type of the input arguments to the pattern.
+
+ * TYPE_OUT: The type of the output of this pattern.
+
+ * Return value: A new stmt that will be used to replace the pattern.
+ Additionally a def_stmt is added.
+
+ a_it = x_t CMP y_t ? b_it : c_it;
+ a_T = (TYPE) a_it; */
+
+static gimple
+vect_recog_mixed_size_cond_pattern (VEC (gimple, heap) **stmts, tree *type_in,
+ tree *type_out)
+{
+ gimple last_stmt = VEC_index (gimple, *stmts, 0);
+ tree cond_expr, then_clause, else_clause;
+ stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt), def_stmt_info;
+ tree type, vectype, comp_vectype, itype, vecitype;
+ enum machine_mode cmpmode;
+ gimple pattern_stmt, def_stmt;
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+
+ if (!is_gimple_assign (last_stmt)
+ || gimple_assign_rhs_code (last_stmt) != COND_EXPR
+ || STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_internal_def)
+ return NULL;
+
+ cond_expr = gimple_assign_rhs1 (last_stmt);
+ then_clause = gimple_assign_rhs2 (last_stmt);
+ else_clause = gimple_assign_rhs3 (last_stmt);
+
+ if (TREE_CODE (then_clause) != INTEGER_CST
+ || TREE_CODE (else_clause) != INTEGER_CST)
+ return NULL;
+
+ if (!COMPARISON_CLASS_P (cond_expr))
+ return NULL;
+
+ comp_vectype
+ = get_vectype_for_scalar_type (TREE_TYPE (TREE_OPERAND (cond_expr, 0)));
+ if (comp_vectype == NULL_TREE)
+ return NULL;
+
+ type = gimple_expr_type (last_stmt);
+ cmpmode = GET_MODE_INNER (TYPE_MODE (comp_vectype));
+
+ if (GET_MODE_BITSIZE (TYPE_MODE (type)) == GET_MODE_BITSIZE (cmpmode))
+ return NULL;
+
+ vectype = get_vectype_for_scalar_type (type);
+ if (vectype == NULL_TREE)
+ return NULL;
+
+ if (expand_vec_cond_expr_p (vectype, comp_vectype))
+ return NULL;
+
+ itype = build_nonstandard_integer_type (GET_MODE_BITSIZE (cmpmode),
+ TYPE_UNSIGNED (type));
+ if (itype == NULL_TREE
+ || GET_MODE_BITSIZE (TYPE_MODE (itype)) != GET_MODE_BITSIZE (cmpmode))
+ return NULL;
+
+ vecitype = get_vectype_for_scalar_type (itype);
+ if (vecitype == NULL_TREE)
+ return NULL;
+
+ if (!expand_vec_cond_expr_p (vecitype, comp_vectype))
+ return NULL;
+
+ if (GET_MODE_BITSIZE (TYPE_MODE (type)) > GET_MODE_BITSIZE (cmpmode))
+ {
+ if (!int_fits_type_p (then_clause, itype)
+ || !int_fits_type_p (else_clause, itype))
+ return NULL;
+ }
+
+ def_stmt
+ = gimple_build_assign_with_ops3 (COND_EXPR,
+ vect_recog_temp_ssa_var (itype, NULL),
+ unshare_expr (cond_expr),
+ fold_convert (itype, then_clause),
+ fold_convert (itype, else_clause));
+ pattern_stmt
+ = gimple_build_assign_with_ops (NOP_EXPR,
+ vect_recog_temp_ssa_var (type, NULL),
+ gimple_assign_lhs (def_stmt), NULL_TREE);
+
+ STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = def_stmt;
+ def_stmt_info = new_stmt_vec_info (def_stmt, loop_vinfo, NULL);
+ set_vinfo_for_stmt (def_stmt, def_stmt_info);
+ STMT_VINFO_VECTYPE (def_stmt_info) = vecitype;
+ *type_in = vecitype;
+ *type_out = vectype;
+
+ return pattern_stmt;
+}
+
+
+/* Helper function of vect_recog_bool_pattern. Called recursively, return
+ true if bool VAR can be optimized that way. */
+
+static bool
+check_bool_pattern (tree var, loop_vec_info loop_vinfo)
+{
+ gimple def_stmt;
+ enum vect_def_type dt;
+ tree def, rhs1;
+ enum tree_code rhs_code;
+
+ if (!vect_is_simple_use (var, loop_vinfo, NULL, &def_stmt, &def, &dt))
+ return false;
+
+ if (dt != vect_internal_def)
+ return false;
+
+ if (!is_gimple_assign (def_stmt))
+ return false;
+
+ if (!has_single_use (def))
+ return false;
+
+ rhs1 = gimple_assign_rhs1 (def_stmt);
+ rhs_code = gimple_assign_rhs_code (def_stmt);
+ switch (rhs_code)
+ {
+ case SSA_NAME:
+ return check_bool_pattern (rhs1, loop_vinfo);
+
+ CASE_CONVERT:
+ if ((TYPE_PRECISION (TREE_TYPE (rhs1)) != 1
+ || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
+ && TREE_CODE (TREE_TYPE (rhs1)) != BOOLEAN_TYPE)
+ return false;
+ return check_bool_pattern (rhs1, loop_vinfo);
+
+ case BIT_NOT_EXPR:
+ return check_bool_pattern (rhs1, loop_vinfo);
+
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (!check_bool_pattern (rhs1, loop_vinfo))
+ return false;
+ return check_bool_pattern (gimple_assign_rhs2 (def_stmt), loop_vinfo);
+
+ default:
+ if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
+ {
+ tree vecitype, comp_vectype;
+
+ comp_vectype = get_vectype_for_scalar_type (TREE_TYPE (rhs1));
+ if (comp_vectype == NULL_TREE)
+ return false;
+
+ if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE)
+ {
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+ tree itype
+ = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 0);
+ vecitype = get_vectype_for_scalar_type (itype);
+ if (vecitype == NULL_TREE)
+ return false;
+ }
+ else
+ vecitype = comp_vectype;
+ return expand_vec_cond_expr_p (vecitype, comp_vectype);
+ }
+ return false;
+ }
+}
+
+
+/* Helper function of adjust_bool_pattern. Add a cast to TYPE to a previous
+ stmt (SSA_NAME_DEF_STMT of VAR) by moving the COND_EXPR from RELATED_STMT
+ to PATTERN_DEF_STMT and adding a cast as RELATED_STMT. */
+
+static tree
+adjust_bool_pattern_cast (tree type, tree var)
+{
+ stmt_vec_info stmt_vinfo = vinfo_for_stmt (SSA_NAME_DEF_STMT (var));
+ gimple cast_stmt, pattern_stmt;
+
+ gcc_assert (!STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo));
+ pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
+ STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = pattern_stmt;
+ cast_stmt
+ = gimple_build_assign_with_ops (NOP_EXPR,
+ vect_recog_temp_ssa_var (type, NULL),
+ gimple_assign_lhs (pattern_stmt),
+ NULL_TREE);
+ STMT_VINFO_RELATED_STMT (stmt_vinfo) = cast_stmt;
+ return gimple_assign_lhs (cast_stmt);
+}
+
+
+/* Helper function of vect_recog_bool_pattern. Do the actual transformations,
+ recursively. VAR is an SSA_NAME that should be transformed from bool
+ to a wider integer type, OUT_TYPE is the desired final integer type of
+ the whole pattern, TRUEVAL should be NULL unless optimizing
+ BIT_AND_EXPR into a COND_EXPR with one integer from one of the operands
+ in the then_clause, STMTS is where statements with added pattern stmts
+ should be pushed to. */
+
+static tree
+adjust_bool_pattern (tree var, tree out_type, tree trueval,
+ VEC (gimple, heap) **stmts)
+{
+ gimple stmt = SSA_NAME_DEF_STMT (var);
+ enum tree_code rhs_code, def_rhs_code;
+ tree itype, cond_expr, rhs1, rhs2, irhs1, irhs2;
+ location_t loc;
+ gimple pattern_stmt, def_stmt;
+
+ rhs1 = gimple_assign_rhs1 (stmt);
+ rhs2 = gimple_assign_rhs2 (stmt);
+ rhs_code = gimple_assign_rhs_code (stmt);
+ loc = gimple_location (stmt);
+ switch (rhs_code)
+ {
+ case SSA_NAME:
+ CASE_CONVERT:
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ itype = TREE_TYPE (irhs1);
+ pattern_stmt
+ = gimple_build_assign_with_ops (SSA_NAME,
+ vect_recog_temp_ssa_var (itype, NULL),
+ irhs1, NULL_TREE);
+ break;
+
+ case BIT_NOT_EXPR:
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ itype = TREE_TYPE (irhs1);
+ pattern_stmt
+ = gimple_build_assign_with_ops (BIT_XOR_EXPR,
+ vect_recog_temp_ssa_var (itype, NULL),
+ irhs1, build_int_cst (itype, 1));
+ break;
+
+ case BIT_AND_EXPR:
+ /* Try to optimize x = y & (a < b ? 1 : 0); into
+ x = (a < b ? y : 0);
+
+ E.g. for:
+ bool a_b, b_b, c_b;
+ TYPE d_T;
+
+ S1 a_b = x1 CMP1 y1;
+ S2 b_b = x2 CMP2 y2;
+ S3 c_b = a_b & b_b;
+ S4 d_T = (TYPE) c_b;
+
+ we would normally emit:
+
+ S1' a_T = x1 CMP1 y1 ? 1 : 0;
+ S2' b_T = x2 CMP2 y2 ? 1 : 0;
+ S3' c_T = a_T & b_T;
+ S4' d_T = c_T;
+
+ but we can save one stmt by using the
+ result of one of the COND_EXPRs in the other COND_EXPR and leave
+ BIT_AND_EXPR stmt out:
+
+ S1' a_T = x1 CMP1 y1 ? 1 : 0;
+ S3' c_T = x2 CMP2 y2 ? a_T : 0;
+ S4' f_T = c_T;
+
+ At least when VEC_COND_EXPR is implemented using masks
+ cond ? 1 : 0 is as expensive as cond ? var : 0, in both cases it
+ computes the comparison masks and ands it, in one case with
+ all ones vector, in the other case with a vector register.
+ Don't do this for BIT_IOR_EXPR, because cond ? 1 : var; is
+ often more expensive. */
+ def_stmt = SSA_NAME_DEF_STMT (rhs2);
+ def_rhs_code = gimple_assign_rhs_code (def_stmt);
+ if (TREE_CODE_CLASS (def_rhs_code) == tcc_comparison)
+ {
+ tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ if (TYPE_PRECISION (TREE_TYPE (irhs1))
+ == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
+ {
+ gimple tstmt;
+ stmt_vec_info stmt_def_vinfo = vinfo_for_stmt (def_stmt);
+ irhs2 = adjust_bool_pattern (rhs2, out_type, irhs1, stmts);
+ tstmt = VEC_pop (gimple, *stmts);
+ gcc_assert (tstmt == def_stmt);
+ VEC_quick_push (gimple, *stmts, stmt);
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt))
+ = STMT_VINFO_RELATED_STMT (stmt_def_vinfo);
+ gcc_assert (!STMT_VINFO_PATTERN_DEF_STMT (stmt_def_vinfo));
+ STMT_VINFO_RELATED_STMT (stmt_def_vinfo) = NULL;
+ return irhs2;
+ }
+ else
+ irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
+ goto and_ior_xor;
+ }
+ def_stmt = SSA_NAME_DEF_STMT (rhs1);
+ def_rhs_code = gimple_assign_rhs_code (def_stmt);
+ if (TREE_CODE_CLASS (def_rhs_code) == tcc_comparison)
+ {
+ tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
+ irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
+ if (TYPE_PRECISION (TREE_TYPE (irhs2))
+ == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
+ {
+ gimple tstmt;
+ stmt_vec_info stmt_def_vinfo = vinfo_for_stmt (def_stmt);
+ irhs1 = adjust_bool_pattern (rhs1, out_type, irhs2, stmts);
+ tstmt = VEC_pop (gimple, *stmts);
+ gcc_assert (tstmt == def_stmt);
+ VEC_quick_push (gimple, *stmts, stmt);
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt))
+ = STMT_VINFO_RELATED_STMT (stmt_def_vinfo);
+ gcc_assert (!STMT_VINFO_PATTERN_DEF_STMT (stmt_def_vinfo));
+ STMT_VINFO_RELATED_STMT (stmt_def_vinfo) = NULL;
+ return irhs1;
+ }
+ else
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ goto and_ior_xor;
+ }
+ /* FALLTHRU */
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
+ and_ior_xor:
+ if (TYPE_PRECISION (TREE_TYPE (irhs1))
+ != TYPE_PRECISION (TREE_TYPE (irhs2)))
+ {
+ int prec1 = TYPE_PRECISION (TREE_TYPE (irhs1));
+ int prec2 = TYPE_PRECISION (TREE_TYPE (irhs2));
+ int out_prec = TYPE_PRECISION (out_type);
+ if (absu_hwi (out_prec - prec1) < absu_hwi (out_prec - prec2))
+ irhs2 = adjust_bool_pattern_cast (TREE_TYPE (irhs1), rhs2);
+ else if (absu_hwi (out_prec - prec1) > absu_hwi (out_prec - prec2))
+ irhs1 = adjust_bool_pattern_cast (TREE_TYPE (irhs2), rhs1);
+ else
+ {
+ irhs1 = adjust_bool_pattern_cast (out_type, rhs1);
+ irhs2 = adjust_bool_pattern_cast (out_type, rhs2);
+ }
+ }
+ itype = TREE_TYPE (irhs1);
+ pattern_stmt
+ = gimple_build_assign_with_ops (rhs_code,
+ vect_recog_temp_ssa_var (itype, NULL),
+ irhs1, irhs2);
+ break;
+
+ default:
+ gcc_assert (TREE_CODE_CLASS (rhs_code) == tcc_comparison);
+ if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE
+ || TYPE_UNSIGNED (TREE_TYPE (rhs1)))
+ {
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+ itype
+ = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 0);
+ }
+ else
+ itype = TREE_TYPE (rhs1);
+ cond_expr = build2_loc (loc, rhs_code, itype, rhs1, rhs2);
+ if (trueval == NULL_TREE)
+ trueval = build_int_cst (itype, 1);
+ else
+ gcc_checking_assert (useless_type_conversion_p (itype,
+ TREE_TYPE (trueval)));
+ pattern_stmt
+ = gimple_build_assign_with_ops3 (COND_EXPR,
+ vect_recog_temp_ssa_var (itype, NULL),
+ cond_expr, trueval,
+ build_int_cst (itype, 0));
+ break;
+ }
+
+ VEC_safe_push (gimple, heap, *stmts, stmt);
+ gimple_set_location (pattern_stmt, loc);
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt)) = pattern_stmt;
+ return gimple_assign_lhs (pattern_stmt);
+}
+
+
+/* Function vect_recog_bool_pattern
+
+ Try to find pattern like following:
+
+ bool a_b, b_b, c_b, d_b, e_b;
+ TYPE f_T;
+ loop:
+ S1 a_b = x1 CMP1 y1;
+ S2 b_b = x2 CMP2 y2;
+ S3 c_b = a_b & b_b;
+ S4 d_b = x3 CMP3 y3;
+ S5 e_b = c_b | d_b;
+ S6 f_T = (TYPE) e_b;
+
+ where type 'TYPE' is an integral type.
+
+ Input:
+
+ * LAST_STMT: A stmt at the end from which the pattern
+ search begins, i.e. cast of a bool to
+ an integer type.
+
+ Output:
+
+ * TYPE_IN: The type of the input arguments to the pattern.
+
+ * TYPE_OUT: The type of the output of this pattern.
+
+ * Return value: A new stmt that will be used to replace the pattern.
+
+ Assuming size of TYPE is the same as size of all comparisons
+ (otherwise some casts would be added where needed), the above
+ sequence we create related pattern stmts:
+ S1' a_T = x1 CMP1 y1 ? 1 : 0;
+ S3' c_T = x2 CMP2 y2 ? a_T : 0;
+ S4' d_T = x3 CMP3 y3 ? 1 : 0;
+ S5' e_T = c_T | d_T;
+ S6' f_T = e_T;
+
+ Instead of the above S3' we could emit:
+ S2' b_T = x2 CMP2 y2 ? 1 : 0;
+ S3' c_T = a_T | b_T;
+ but the above is more efficient. */
+
+static gimple
+vect_recog_bool_pattern (VEC (gimple, heap) **stmts, tree *type_in,
+ tree *type_out)
+{
+ gimple last_stmt = VEC_pop (gimple, *stmts);
+ enum tree_code rhs_code;
+ tree var, lhs, rhs, vectype;
+ stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+ gimple pattern_stmt;
+
+ if (!is_gimple_assign (last_stmt))
+ return NULL;
+
+ var = gimple_assign_rhs1 (last_stmt);
+ lhs = gimple_assign_lhs (last_stmt);
+
+ if ((TYPE_PRECISION (TREE_TYPE (var)) != 1
+ || !TYPE_UNSIGNED (TREE_TYPE (var)))
+ && TREE_CODE (TREE_TYPE (var)) != BOOLEAN_TYPE)
+ return NULL;
+
+ rhs_code = gimple_assign_rhs_code (last_stmt);
+ if (CONVERT_EXPR_CODE_P (rhs_code))
+ {
+ if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE)
+ return NULL;
+ vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs));
+ if (vectype == NULL_TREE)
+ return NULL;
+
+ if (!check_bool_pattern (var, loop_vinfo))
+ return NULL;
+
+ rhs = adjust_bool_pattern (var, TREE_TYPE (lhs), NULL_TREE, stmts);
+ lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
+ if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ pattern_stmt
+ = gimple_build_assign_with_ops (SSA_NAME, lhs, rhs, NULL_TREE);
+ else
+ pattern_stmt
+ = gimple_build_assign_with_ops (NOP_EXPR, lhs, rhs, NULL_TREE);
+ *type_out = vectype;
+ *type_in = vectype;
+ VEC_safe_push (gimple, heap, *stmts, last_stmt);
+ return pattern_stmt;
+ }
+ else
+ return NULL;
+}
+
/* Mark statements that are involved in a pattern. */
@@ -1245,14 +1965,18 @@ vect_mark_pattern_stmts (gimple orig_stmt, gimple pattern_stmt,
if (STMT_VINFO_PATTERN_DEF_STMT (pattern_stmt_info))
{
def_stmt = STMT_VINFO_PATTERN_DEF_STMT (pattern_stmt_info);
- set_vinfo_for_stmt (def_stmt,
- new_stmt_vec_info (def_stmt, loop_vinfo, NULL));
- gimple_set_bb (def_stmt, gimple_bb (orig_stmt));
def_stmt_info = vinfo_for_stmt (def_stmt);
+ if (def_stmt_info == NULL)
+ {
+ def_stmt_info = new_stmt_vec_info (def_stmt, loop_vinfo, NULL);
+ set_vinfo_for_stmt (def_stmt, def_stmt_info);
+ }
+ gimple_set_bb (def_stmt, gimple_bb (orig_stmt));
STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt;
STMT_VINFO_DEF_TYPE (def_stmt_info)
= STMT_VINFO_DEF_TYPE (orig_stmt_info);
- STMT_VINFO_VECTYPE (def_stmt_info) = pattern_vectype;
+ if (STMT_VINFO_VECTYPE (def_stmt_info) == NULL_TREE)
+ STMT_VINFO_VECTYPE (def_stmt_info) = pattern_vectype;
}
}
@@ -1279,9 +2003,9 @@ vect_mark_pattern_stmts (gimple orig_stmt, gimple pattern_stmt,
for vect_recog_pattern. */
static void
-vect_pattern_recog_1 (
- gimple (* vect_recog_func) (VEC (gimple, heap) **, tree *, tree *),
- gimple_stmt_iterator si)
+vect_pattern_recog_1 (vect_recog_func_ptr vect_recog_func,
+ gimple_stmt_iterator si,
+ VEC (gimple, heap) **stmts_to_replace)
{
gimple stmt = gsi_stmt (si), pattern_stmt;
stmt_vec_info stmt_info;
@@ -1291,14 +2015,14 @@ vect_pattern_recog_1 (
enum tree_code code;
int i;
gimple next;
- VEC (gimple, heap) *stmts_to_replace = VEC_alloc (gimple, heap, 1);
- VEC_quick_push (gimple, stmts_to_replace, stmt);
- pattern_stmt = (* vect_recog_func) (&stmts_to_replace, &type_in, &type_out);
+ VEC_truncate (gimple, *stmts_to_replace, 0);
+ VEC_quick_push (gimple, *stmts_to_replace, stmt);
+ pattern_stmt = (* vect_recog_func) (stmts_to_replace, &type_in, &type_out);
if (!pattern_stmt)
return;
- stmt = VEC_last (gimple, stmts_to_replace);
+ stmt = VEC_last (gimple, *stmts_to_replace);
stmt_info = vinfo_for_stmt (stmt);
loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
@@ -1306,8 +2030,6 @@ vect_pattern_recog_1 (
{
/* No need to check target support (already checked by the pattern
recognition function). */
- if (type_out)
- gcc_assert (VECTOR_MODE_P (TYPE_MODE (type_out)));
pattern_vectype = type_out ? type_out : type_in;
}
else
@@ -1363,8 +2085,8 @@ vect_pattern_recog_1 (
/* It is possible that additional pattern stmts are created and inserted in
STMTS_TO_REPLACE. We create a stmt_info for each of them, and mark the
relevant statements. */
- for (i = 0; VEC_iterate (gimple, stmts_to_replace, i, stmt)
- && (unsigned) i < (VEC_length (gimple, stmts_to_replace) - 1);
+ for (i = 0; VEC_iterate (gimple, *stmts_to_replace, i, stmt)
+ && (unsigned) i < (VEC_length (gimple, *stmts_to_replace) - 1);
i++)
{
stmt_info = vinfo_for_stmt (stmt);
@@ -1377,8 +2099,6 @@ vect_pattern_recog_1 (
vect_mark_pattern_stmts (stmt, pattern_stmt, NULL_TREE);
}
-
- VEC_free (gimple, heap, stmts_to_replace);
}
@@ -1467,7 +2187,8 @@ vect_pattern_recog (loop_vec_info loop_vinfo)
unsigned int nbbs = loop->num_nodes;
gimple_stmt_iterator si;
unsigned int i, j;
- gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *);
+ vect_recog_func_ptr vect_recog_func;
+ VEC (gimple, heap) *stmts_to_replace = VEC_alloc (gimple, heap, 1);
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_pattern_recog ===");
@@ -1482,9 +2203,12 @@ vect_pattern_recog (loop_vec_info loop_vinfo)
/* Scan over all generic vect_recog_xxx_pattern functions. */
for (j = 0; j < NUM_PATTERNS; j++)
{
- vect_recog_func_ptr = vect_vect_recog_func_ptrs[j];
- vect_pattern_recog_1 (vect_recog_func_ptr, si);
+ vect_recog_func = vect_vect_recog_func_ptrs[j];
+ vect_pattern_recog_1 (vect_recog_func, si,
+ &stmts_to_replace);
}
}
}
+
+ VEC_free (gimple, heap, stmts_to_replace);
}
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 4b205bf332a..f131f1eec23 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -1,5 +1,5 @@
/* SLP - Basic Block Vectorization
- Copyright (C) 2007, 2008, 2009, 2010
+ Copyright (C) 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com>
and Ira Rosen <irar@il.ibm.com>
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "optabs.h"
#include "tree-vectorizer.h"
+#include "langhooks.h"
/* Extract the location of the basic block in the source code.
Return the basic block location if succeed and NULL if not. */
@@ -115,13 +116,15 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
tree oprnd;
unsigned int i, number_of_oprnds;
- tree def;
+ tree def[2];
gimple def_stmt;
enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
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 = NULL;
+ enum tree_code rhs_code;
+ bool different_types = false;
if (loop_vinfo)
loop = LOOP_VINFO_LOOP (loop_vinfo);
@@ -133,7 +136,7 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
oprnd = gimple_op (stmt, i + 1);
- if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def,
+ if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def[i],
&dt[i])
|| (!def_stmt && dt[i] != vect_constant_def))
{
@@ -188,11 +191,11 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
switch (gimple_code (def_stmt))
{
case GIMPLE_PHI:
- def = gimple_phi_result (def_stmt);
+ def[i] = gimple_phi_result (def_stmt);
break;
case GIMPLE_ASSIGN:
- def = gimple_assign_lhs (def_stmt);
+ def[i] = gimple_assign_lhs (def_stmt);
break;
default:
@@ -206,8 +209,8 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
/* op0 of the first stmt of the group - store its info. */
*first_stmt_dt0 = dt[i];
- if (def)
- *first_stmt_def0_type = TREE_TYPE (def);
+ if (def[i])
+ *first_stmt_def0_type = TREE_TYPE (def[i]);
else
*first_stmt_const_oprnd = oprnd;
@@ -227,8 +230,8 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
/* op1 of the first stmt of the group - store its info. */
*first_stmt_dt1 = dt[i];
- if (def)
- *first_stmt_def1_type = TREE_TYPE (def);
+ if (def[i])
+ *first_stmt_def1_type = TREE_TYPE (def[i]);
else
{
/* We assume that the stmt contains only one constant
@@ -254,24 +257,56 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
&& ((*first_stmt_dt0 != dt[i]
&& !(*first_stmt_dt0 == vect_reduction_def
&& dt[i] == vect_internal_def))
- || (*first_stmt_def0_type && def
+ || (*first_stmt_def0_type && def[0]
&& !types_compatible_p (*first_stmt_def0_type,
- TREE_TYPE (def)))))
+ TREE_TYPE (def[0])))))
|| (i == 1
&& ((*first_stmt_dt1 != dt[i]
&& !(*first_stmt_dt1 == vect_reduction_def
&& dt[i] == vect_internal_def))
- || (*first_stmt_def1_type && def
+ || (*first_stmt_def1_type && def[1]
&& !types_compatible_p (*first_stmt_def1_type,
- TREE_TYPE (def)))))
- || (!def
+ TREE_TYPE (def[1])))))
+ || (!def[i]
&& !types_compatible_p (TREE_TYPE (*first_stmt_const_oprnd),
- TREE_TYPE (oprnd))))
+ TREE_TYPE (oprnd)))
+ || different_types)
{
- if (vect_print_dump_info (REPORT_SLP))
- fprintf (vect_dump, "Build SLP failed: different types ");
+ if (i != number_of_oprnds - 1)
+ different_types = true;
+ else
+ {
+ if (is_gimple_assign (stmt)
+ && (rhs_code = gimple_assign_rhs_code (stmt))
+ && TREE_CODE_CLASS (rhs_code) == tcc_binary
+ && commutative_tree_code (rhs_code)
+ && *first_stmt_dt0 == dt[1]
+ && *first_stmt_dt1 == dt[0]
+ && def[0] && def[1]
+ && !(*first_stmt_def0_type
+ && !types_compatible_p (*first_stmt_def0_type,
+ TREE_TYPE (def[1])))
+ && !(*first_stmt_def1_type
+ && !types_compatible_p (*first_stmt_def1_type,
+ TREE_TYPE (def[0]))))
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ {
+ fprintf (vect_dump, "Swapping operands of ");
+ print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
+ }
+
+ swap_tree_operands (stmt, gimple_assign_rhs1_ptr (stmt),
+ gimple_assign_rhs2_ptr (stmt));
+ }
+ else
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ fprintf (vect_dump, "Build SLP failed: different types ");
- return false;
+ return false;
+ }
+ }
}
}
}
@@ -285,10 +320,10 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
case vect_internal_def:
case vect_reduction_def:
- if (i == 0)
+ if ((i == 0 && !different_types) || (i == 1 && different_types))
VEC_safe_push (gimple, heap, *def_stmts0, def_stmt);
else
- VEC_safe_push (gimple, heap, *def_stmts1, def_stmt);
+ VEC_safe_push (gimple, heap, *def_stmts1, def_stmt);
break;
default:
@@ -296,7 +331,7 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
if (vect_print_dump_info (REPORT_SLP))
{
fprintf (vect_dump, "Build SLP failed: illegal type of def ");
- print_generic_expr (vect_dump, def, TDF_SLIM);
+ print_generic_expr (vect_dump, def[i], TDF_SLIM);
}
return false;
@@ -319,7 +354,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
int ncopies_for_cost, unsigned int *max_nunits,
VEC (int, heap) **load_permutation,
VEC (slp_tree, heap) **loads,
- unsigned int vectorization_factor)
+ unsigned int vectorization_factor, bool *loads_permuted)
{
VEC (gimple, heap) *def_stmts0 = VEC_alloc (gimple, heap, group_size);
VEC (gimple, heap) *def_stmts1 = VEC_alloc (gimple, heap, group_size);
@@ -454,6 +489,11 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
}
}
}
+ else if (rhs_code == WIDEN_LSHIFT_EXPR)
+ {
+ need_same_oprnds = true;
+ first_op1 = gimple_assign_rhs2 (stmt);
+ }
}
else
{
@@ -530,7 +570,8 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
/* Check that the size of interleaved loads group is not
greater than the SLP group size. */
- if (GROUP_SIZE (vinfo_for_stmt (stmt)) > ncopies * group_size)
+ if (loop_vinfo
+ && GROUP_SIZE (vinfo_for_stmt (stmt)) > ncopies * group_size)
{
if (vect_print_dump_info (REPORT_SLP))
{
@@ -651,19 +692,22 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
/* Strided loads were reached - stop the recursion. */
if (stop_recursion)
{
+ VEC_safe_push (slp_tree, heap, *loads, *node);
if (permutation)
{
- VEC_safe_push (slp_tree, heap, *loads, *node);
+
+ *loads_permuted = true;
*inside_cost
+= targetm.vectorize.builtin_vectorization_cost (vec_perm, NULL, 0)
* group_size;
}
else
- {
- /* We don't check here complex numbers chains, so we keep them in
- LOADS for further check in vect_supported_load_permutation_p. */
+ {
+ /* We don't check here complex numbers chains, so we set
+ LOADS_PERMUTED for further check in
+ vect_supported_load_permutation_p. */
if (rhs_code == REALPART_EXPR || rhs_code == IMAGPART_EXPR)
- VEC_safe_push (slp_tree, heap, *loads, *node);
+ *loads_permuted = true;
}
return true;
@@ -682,7 +726,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
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,
- vectorization_factor))
+ vectorization_factor, loads_permuted))
return false;
SLP_TREE_LEFT (*node) = left_node;
@@ -700,7 +744,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
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,
- vectorization_factor))
+ vectorization_factor, loads_permuted))
return false;
SLP_TREE_RIGHT (*node) = right_node;
@@ -886,8 +930,10 @@ vect_supported_load_permutation_p (slp_instance slp_instn, int group_size,
bool supported, bad_permutation = false;
sbitmap load_index;
slp_tree node, other_complex_node;
- gimple stmt, first = NULL, other_node_first;
+ gimple stmt, first = NULL, other_node_first, load, next_load, first_load;
unsigned complex_numbers = 0;
+ struct data_reference *dr;
+ bb_vec_info bb_vinfo;
/* FORNOW: permutations are only supported in SLP. */
if (!slp_instn)
@@ -1049,6 +1095,76 @@ vect_supported_load_permutation_p (slp_instance slp_instn, int group_size,
}
}
+ /* In basic block vectorization we allow any subchain of an interleaving
+ chain.
+ FORNOW: not supported in loop SLP because of realignment compications. */
+ bb_vinfo = STMT_VINFO_BB_VINFO (vinfo_for_stmt (stmt));
+ bad_permutation = false;
+ /* Check that for every node in the instance teh loads form a subchain. */
+ if (bb_vinfo)
+ {
+ FOR_EACH_VEC_ELT (slp_tree, SLP_INSTANCE_LOADS (slp_instn), i, node)
+ {
+ next_load = NULL;
+ first_load = NULL;
+ FOR_EACH_VEC_ELT (gimple, SLP_TREE_SCALAR_STMTS (node), j, load)
+ {
+ if (!first_load)
+ first_load = GROUP_FIRST_ELEMENT (vinfo_for_stmt (load));
+ else if (first_load
+ != GROUP_FIRST_ELEMENT (vinfo_for_stmt (load)))
+ {
+ bad_permutation = true;
+ break;
+ }
+
+ if (j != 0 && next_load != load)
+ {
+ bad_permutation = true;
+ break;
+ }
+
+ next_load = GROUP_NEXT_ELEMENT (vinfo_for_stmt (load));
+ }
+
+ if (bad_permutation)
+ break;
+ }
+
+ /* Check that the alignment of the first load in every subchain, i.e.,
+ the first statement in every load node, is supported. */
+ if (!bad_permutation)
+ {
+ FOR_EACH_VEC_ELT (slp_tree, SLP_INSTANCE_LOADS (slp_instn), i, node)
+ {
+ first_load = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (node), 0);
+ if (first_load
+ != GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_load)))
+ {
+ dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_load));
+ if (vect_supportable_dr_alignment (dr, false)
+ == dr_unaligned_unsupported)
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ {
+ fprintf (vect_dump, "unsupported unaligned load ");
+ print_gimple_stmt (vect_dump, first_load, 0,
+ TDF_SLIM);
+ }
+ bad_permutation = true;
+ break;
+ }
+ }
+ }
+
+ if (!bad_permutation)
+ {
+ VEC_free (int, heap, SLP_INSTANCE_LOAD_PERMUTATION (slp_instn));
+ return true;
+ }
+ }
+ }
+
/* FORNOW: the only supported permutation is 0..01..1.. of length equal to
GROUP_SIZE and where each sequence of same drs is of GROUP_SIZE length as
well (unless it's reduction). */
@@ -1158,6 +1274,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
VEC (int, heap) *load_permutation;
VEC (slp_tree, heap) *loads;
struct data_reference *dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt));
+ bool loads_permuted = false;
if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
{
@@ -1249,7 +1366,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
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))
+ vectorization_factor, &loads_permuted))
{
/* Calculate the unrolling factor based on the smallest type. */
if (max_nunits > nunits)
@@ -1274,7 +1391,8 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
SLP_INSTANCE_LOADS (new_instance) = loads;
SLP_INSTANCE_FIRST_LOAD_STMT (new_instance) = NULL;
SLP_INSTANCE_LOAD_PERMUTATION (new_instance) = load_permutation;
- if (VEC_length (slp_tree, loads))
+
+ if (loads_permuted)
{
if (!vect_supported_load_permutation_p (new_instance, group_size,
load_permutation))
@@ -2226,8 +2344,7 @@ static inline void
vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
tree mask, int first_vec_indx, int second_vec_indx,
gimple_stmt_iterator *gsi, slp_tree node,
- tree builtin_decl, tree vectype,
- VEC(tree,heap) *dr_chain,
+ tree vectype, VEC(tree,heap) *dr_chain,
int ncopies, int vect_stmts_counter)
{
tree perm_dest;
@@ -2251,10 +2368,10 @@ vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
second_vec = VEC_index (tree, dr_chain, second_vec_indx);
/* Generate the permute statement. */
- perm_stmt = gimple_build_call (builtin_decl,
- 3, first_vec, second_vec, mask);
+ perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
+ first_vec, second_vec, mask);
data_ref = make_ssa_name (perm_dest, perm_stmt);
- gimple_call_set_lhs (perm_stmt, data_ref);
+ gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
/* Store the vector statement in NODE. */
@@ -2361,9 +2478,9 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree mask_element_type = NULL_TREE, mask_type;
- int i, j, k, m, scale, mask_nunits, nunits, vec_index = 0, scalar_index;
+ int i, j, k, nunits, vec_index = 0, scalar_index;
slp_tree node;
- tree vectype = STMT_VINFO_VECTYPE (stmt_info), builtin_decl;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
gimple next_scalar_stmt;
int group_size = SLP_INSTANCE_GROUP_SIZE (slp_node_instance);
int first_mask_element;
@@ -2374,35 +2491,24 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
bool mask_fixed = false;
bool needs_first_vector = false;
- if (!targetm.vectorize.builtin_vec_perm)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- {
- fprintf (vect_dump, "no builtin for vect permute for ");
- print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
- }
-
- return false;
- }
-
- builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
- &mask_element_type);
- if (!builtin_decl || !mask_element_type)
+ if (!can_vec_perm_expr_p (vectype, NULL_TREE))
{
if (vect_print_dump_info (REPORT_DETAILS))
{
- fprintf (vect_dump, "no builtin for vect permute for ");
+ fprintf (vect_dump, "no vect permute for ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
-
- return false;
+ return false;
}
+ /* The generic VEC_PERM_EXPR code always uses an integral type of the
+ same size as the vector element being permuted. */
+ mask_element_type
+ = lang_hooks.types.type_for_size
+ (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (vectype))), 1);
mask_type = get_vectype_for_scalar_type (mask_element_type);
- mask_nunits = TYPE_VECTOR_SUBPARTS (mask_type);
- mask = (int *) xmalloc (sizeof (int) * mask_nunits);
nunits = TYPE_VECTOR_SUBPARTS (vectype);
- scale = mask_nunits / nunits;
+ mask = (int *) xmalloc (sizeof (int) * nunits);
unroll_factor = SLP_INSTANCE_UNROLLING_FACTOR (slp_node_instance);
/* The number of vector stmts to generate based only on SLP_NODE_INSTANCE
@@ -2425,8 +2531,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
for b's: b0b0b0b1 b1b1b2b2 b2b3b3b3
...
- The masks for a's should be: {0,0,0,3} {3,3,6,6} {6,9,9,9} (in target
- scpecific type, e.g., in bytes for Altivec.
+ The masks for a's should be: {0,0,0,3} {3,3,6,6} {6,9,9,9}.
The last mask is illegal since we assume two operands for permute
operation, and the mask element values can't be outside that range.
Hence, the last mask must be converted into {2,5,5,5}.
@@ -2451,20 +2556,17 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
{
for (k = 0; k < group_size; k++)
{
- first_mask_element = (i + j * group_size) * scale;
- for (m = 0; m < scale; m++)
- {
- if (!vect_get_mask_element (stmt, first_mask_element, m,
- mask_nunits, only_one_vec, index, mask,
- &current_mask_element, &need_next_vector,
- &number_of_mask_fixes, &mask_fixed,
- &needs_first_vector))
- return false;
-
- mask[index++] = current_mask_element;
- }
+ first_mask_element = i + j * group_size;
+ if (!vect_get_mask_element (stmt, first_mask_element, 0,
+ nunits, only_one_vec, index,
+ mask, &current_mask_element,
+ &need_next_vector,
+ &number_of_mask_fixes, &mask_fixed,
+ &needs_first_vector))
+ return false;
+ mask[index++] = current_mask_element;
- if (index == mask_nunits)
+ if (index == nunits)
{
tree mask_vec = NULL;
@@ -2476,8 +2578,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
mask_vec = build_vector (mask_type, mask_vec);
index = 0;
- if (!targetm.vectorize.builtin_vec_perm_ok (vectype,
- mask_vec))
+ if (!can_vec_perm_expr_p (vectype, mask_vec))
{
if (vect_print_dump_info (REPORT_DETAILS))
{
@@ -2501,7 +2602,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
vect_create_mask_and_perm (stmt, next_scalar_stmt,
mask_vec, first_vec_index, second_vec_index,
- gsi, node, builtin_decl, vectype, dr_chain,
+ gsi, node, vectype, dr_chain,
ncopies, vect_stmts_counter++);
}
}
@@ -2583,10 +2684,11 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
/* Loads should be inserted before the first load. */
if (SLP_INSTANCE_FIRST_LOAD_STMT (instance)
&& STMT_VINFO_STRIDED_ACCESS (stmt_info)
- && !REFERENCE_CLASS_P (gimple_get_lhs (stmt)))
+ && !REFERENCE_CLASS_P (gimple_get_lhs (stmt))
+ && SLP_INSTANCE_LOAD_PERMUTATION (instance))
si = gsi_for_stmt (SLP_INSTANCE_FIRST_LOAD_STMT (instance));
else if (is_pattern_stmt_p (stmt_info))
- si = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+ si = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
else
si = gsi_for_stmt (stmt);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 8c2edadba13..b8f6336d2b3 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -652,9 +652,25 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
have to scan the RHS or function arguments instead. */
if (is_gimple_assign (stmt))
{
- for (i = 1; i < gimple_num_ops (stmt); i++)
+ enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+ tree op = gimple_assign_rhs1 (stmt);
+
+ i = 1;
+ if (rhs_code == COND_EXPR && COMPARISON_CLASS_P (op))
+ {
+ if (!process_use (stmt, TREE_OPERAND (op, 0), loop_vinfo,
+ live_p, relevant, &worklist)
+ || !process_use (stmt, TREE_OPERAND (op, 1), loop_vinfo,
+ live_p, relevant, &worklist))
+ {
+ VEC_free (gimple, heap, worklist);
+ return false;
+ }
+ i = 2;
+ }
+ for (; i < gimple_num_ops (stmt); i++)
{
- tree op = gimple_op (stmt, i);
+ op = gimple_op (stmt, i);
if (!process_use (stmt, op, loop_vinfo, live_p, relevant,
&worklist))
{
@@ -3317,6 +3333,7 @@ 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;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ unsigned int k;
if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
@@ -3333,7 +3350,8 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
code = gimple_assign_rhs_code (stmt);
if (!CONVERT_EXPR_CODE_P (code)
- && code != WIDEN_MULT_EXPR)
+ && code != WIDEN_MULT_EXPR
+ && code != WIDEN_LSHIFT_EXPR)
return false;
scalar_dest = gimple_assign_lhs (stmt);
@@ -3361,7 +3379,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
bool ok;
op1 = gimple_assign_rhs2 (stmt);
- if (code == WIDEN_MULT_EXPR)
+ if (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR)
{
/* For WIDEN_MULT_EXPR, if OP0 is a constant, use the type of
OP1. */
@@ -3438,7 +3456,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
fprintf (vect_dump, "transform type promotion operation. ncopies = %d.",
ncopies);
- if (code == WIDEN_MULT_EXPR)
+ if (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR)
{
if (CONSTANT_CLASS_P (op0))
op0 = fold_convert (TREE_TYPE (op1), op0);
@@ -3479,6 +3497,8 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
if (op_type == binary_op)
vec_oprnds1 = VEC_alloc (tree, heap, 1);
}
+ else if (code == WIDEN_LSHIFT_EXPR)
+ vec_oprnds1 = VEC_alloc (tree, heap, slp_node->vec_stmts_size);
/* In case the vectorization factor (VF) is bigger than the number
of elements that we can fit in a vectype (nunits), we have to generate
@@ -3492,15 +3512,33 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
if (j == 0)
{
if (slp_node)
- vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
- &vec_oprnds1, -1);
- else
+ {
+ if (code == WIDEN_LSHIFT_EXPR)
+ {
+ vec_oprnd1 = op1;
+ /* Store vec_oprnd1 for every vector stmt to be created
+ for SLP_NODE. We check during the analysis that all
+ the shift arguments are the same. */
+ for (k = 0; k < slp_node->vec_stmts_size - 1; k++)
+ VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
+
+ vect_get_slp_defs (op0, NULL_TREE, slp_node, &vec_oprnds0, NULL,
+ -1);
+ }
+ else
+ vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
+ &vec_oprnds1, -1);
+ }
+ else
{
vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
VEC_quick_push (tree, vec_oprnds0, vec_oprnd0);
if (op_type == binary_op)
{
- vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
+ if (code == WIDEN_LSHIFT_EXPR)
+ vec_oprnd1 = op1;
+ else
+ vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
}
}
@@ -3511,7 +3549,10 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
VEC_replace (tree, vec_oprnds0, 0, vec_oprnd0);
if (op_type == binary_op)
{
- vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
+ if (code == WIDEN_LSHIFT_EXPR)
+ vec_oprnd1 = op1;
+ else
+ vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
VEC_replace (tree, vec_oprnds1, 0, vec_oprnd1);
}
}
@@ -3980,41 +4021,33 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
}
/* Given a vector type VECTYPE returns a builtin DECL to be used
- for vector permutation and stores a mask into *MASK that implements
- reversal of the vector elements. If that is impossible to do
- returns NULL (and *MASK is unchanged). */
+ for vector permutation and returns the mask that implements
+ reversal of the vector elements. If that is impossible to do,
+ returns NULL. */
static tree
-perm_mask_for_reverse (tree vectype, tree *mask)
+perm_mask_for_reverse (tree vectype)
{
- tree builtin_decl;
- tree mask_element_type, mask_type;
- tree mask_vec = NULL;
- int i;
- int nunits;
- if (!targetm.vectorize.builtin_vec_perm)
- return NULL;
+ tree mask_element_type, mask_type, mask_vec = NULL;
+ int i, nunits;
- builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
- &mask_element_type);
- if (!builtin_decl || !mask_element_type)
+ if (!can_vec_perm_expr_p (vectype, NULL_TREE))
return NULL;
+ mask_element_type
+ = lang_hooks.types.type_for_size
+ (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (vectype))), 1);
mask_type = get_vectype_for_scalar_type (mask_element_type);
nunits = TYPE_VECTOR_SUBPARTS (vectype);
- if (!mask_type
- || TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
- return NULL;
for (i = 0; i < nunits; i++)
mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec);
mask_vec = build_vector (mask_type, mask_vec);
- if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec))
+ if (!can_vec_perm_expr_p (vectype, mask_vec))
return NULL;
- if (mask)
- *mask = mask_vec;
- return builtin_decl;
+
+ return mask_vec;
}
/* Given a vector variable X, that was generated for the scalar LHS of
@@ -4025,27 +4058,16 @@ static tree
reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi)
{
tree vectype = TREE_TYPE (x);
- tree mask_vec, builtin_decl;
- tree perm_dest, data_ref;
+ tree mask_vec, perm_dest, data_ref;
gimple perm_stmt;
- builtin_decl = perm_mask_for_reverse (vectype, &mask_vec);
+ mask_vec = perm_mask_for_reverse (vectype);
perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype);
/* Generate the permute statement. */
- perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec);
- if (!useless_type_conversion_p (vectype,
- TREE_TYPE (TREE_TYPE (builtin_decl))))
- {
- tree tem = create_tmp_reg (TREE_TYPE (TREE_TYPE (builtin_decl)), NULL);
- tem = make_ssa_name (tem, perm_stmt);
- gimple_call_set_lhs (perm_stmt, tem);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
- perm_stmt = gimple_build_assign (NULL_TREE,
- build1 (VIEW_CONVERT_EXPR,
- vectype, tem));
- }
+ perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
+ x, x, mask_vec);
data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
@@ -4221,7 +4243,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
fprintf (vect_dump, "negative step but alignment required.");
return false;
}
- if (!perm_mask_for_reverse (vectype, NULL))
+ if (!perm_mask_for_reverse (vectype))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "negative step and reversing not supported.");
@@ -4244,6 +4266,11 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
if (strided_load)
{
first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
+ if (slp
+ && !SLP_INSTANCE_LOAD_PERMUTATION (slp_node_instance)
+ && first_stmt != VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0))
+ first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0);
+
/* Check if the chain of loads is already vectorized. */
if (STMT_VINFO_VEC_STMT (vinfo_for_stmt (first_stmt)))
{
@@ -5787,6 +5814,19 @@ supportable_widening_operation (enum tree_code code, gimple stmt,
}
break;
+ case WIDEN_LSHIFT_EXPR:
+ if (BYTES_BIG_ENDIAN)
+ {
+ c1 = VEC_WIDEN_LSHIFT_HI_EXPR;
+ c2 = VEC_WIDEN_LSHIFT_LO_EXPR;
+ }
+ else
+ {
+ c2 = VEC_WIDEN_LSHIFT_HI_EXPR;
+ c1 = VEC_WIDEN_LSHIFT_LO_EXPR;
+ }
+ break;
+
CASE_CONVERT:
if (BYTES_BIG_ENDIAN)
{
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 3fe8b620c15..c27e76ca7ac 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1,5 +1,5 @@
/* Vectorizer
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com>
@@ -902,7 +902,7 @@ extern void vect_slp_transform_bb (basic_block);
Additional pattern recognition functions can (and will) be added
in the future. */
typedef gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *);
-#define NUM_PATTERNS 5
+#define NUM_PATTERNS 8
void vect_pattern_recog (loop_vec_info);
/* In tree-vectorizer.c. */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 56fc5a20b2b..248bc61926f 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1519,7 +1519,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
limit = avoid_overflow_infinity (limit);
- type = TREE_TYPE (limit);
+ type = TREE_TYPE (var);
gcc_assert (limit != var);
/* For pointer arithmetic, we only keep track of pointer equality
@@ -1693,8 +1693,8 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
/* For LT_EXPR, we create the range [MIN, MAX - 1]. */
if (cond_code == LT_EXPR)
{
- tree one = build_int_cst (type, 1);
- max = fold_build2 (MINUS_EXPR, type, max, one);
+ tree one = build_int_cst (TREE_TYPE (max), 1);
+ max = fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, one);
if (EXPR_P (max))
TREE_NO_WARNING (max) = 1;
}
@@ -1728,8 +1728,8 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
/* For GT_EXPR, we create the range [MIN + 1, MAX]. */
if (cond_code == GT_EXPR)
{
- tree one = build_int_cst (type, 1);
- min = fold_build2 (PLUS_EXPR, type, min, one);
+ tree one = build_int_cst (TREE_TYPE (min), 1);
+ min = fold_build2 (PLUS_EXPR, TREE_TYPE (min), min, one);
if (EXPR_P (min))
TREE_NO_WARNING (min) = 1;
}
@@ -2913,15 +2913,10 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]). */
if (POINTER_TYPE_P (type))
{
- if (CONVERT_EXPR_CODE_P (code))
- {
- if (range_is_nonnull (&vr0))
- set_value_range_to_nonnull (vr, type);
- else if (range_is_null (&vr0))
- set_value_range_to_null (vr, type);
- else
- set_value_range_to_varying (vr);
- }
+ if (range_is_nonnull (&vr0))
+ set_value_range_to_nonnull (vr, type);
+ else if (range_is_null (&vr0))
+ set_value_range_to_null (vr, type);
else
set_value_range_to_varying (vr);
return;
@@ -7288,10 +7283,17 @@ simplify_conversion_using_ranges (gimple stmt)
TYPE_UNSIGNED (TREE_TYPE (middleop)));
middlemax = double_int_ext (innermax, TYPE_PRECISION (TREE_TYPE (middleop)),
TYPE_UNSIGNED (TREE_TYPE (middleop)));
- /* If the middle values do not represent a proper range fail. */
- if (double_int_cmp (middlemin, middlemax,
- TYPE_UNSIGNED (TREE_TYPE (middleop))) > 0)
+ /* If the middle values are not equal to the original values fail.
+ But only if the inner cast truncates (thus we ignore differences
+ in extension to handle the case going from a range to an anti-range
+ and back). */
+ if ((TYPE_PRECISION (TREE_TYPE (innerop))
+ > TYPE_PRECISION (TREE_TYPE (middleop)))
+ && (!double_int_equal_p (innermin, middlemin)
+ || !double_int_equal_p (innermax, middlemax)))
return false;
+ /* Require that the final conversion applied to both the original
+ and the intermediate range produces the same result. */
if (!double_int_equal_p (double_int_ext (middlemin,
TYPE_PRECISION (finaltype),
TYPE_UNSIGNED (finaltype)),
diff --git a/gcc/tree.c b/gcc/tree.c
index 3e9750383e1..64c49688575 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4656,10 +4656,9 @@ free_lang_data_in_decl (tree decl)
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == BLOCK)
{
- /* Strip builtins from the translation-unit BLOCK. We still have
- targets without builtin_decl support and also builtins are
- shared nodes and thus we can't use TREE_CHAIN in multiple
- lists. */
+ /* Strip builtins from the translation-unit BLOCK. We still have targets
+ without builtin_decl_explicit support and also builtins are shared
+ nodes and thus we can't use TREE_CHAIN in multiple lists. */
tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl));
while (*nextp)
{
@@ -6942,9 +6941,9 @@ iterative_hash_expr (const_tree t, hashval_t val)
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)])
+ && builtin_decl_explicit_p (DECL_FUNCTION_CODE (t)))
{
- t = built_in_decls[DECL_FUNCTION_CODE (t)];
+ t = builtin_decl_explicit (DECL_FUNCTION_CODE (t));
code = TREE_CODE (t);
}
/* FALL THROUGH */
@@ -9429,8 +9428,7 @@ local_define_builtin (const char *name, tree type, enum built_in_function code,
DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
NULL, DECL_ATTRIBUTES (decl));
- built_in_decls[code] = decl;
- implicit_built_in_decls[code] = decl;
+ set_builtin_decl (code, decl, true);
}
/* Call this function after instantiating all builtins that the language
@@ -9442,22 +9440,22 @@ build_common_builtin_nodes (void)
{
tree tmp, ftype;
- if (built_in_decls[BUILT_IN_MEMCPY] == NULL
- || built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+ if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)
+ || !builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
{
ftype = build_function_type_list (ptr_type_node,
ptr_type_node, const_ptr_type_node,
size_type_node, NULL_TREE);
- if (built_in_decls[BUILT_IN_MEMCPY] == NULL)
+ if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY))
local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY,
"memcpy", ECF_NOTHROW | ECF_LEAF);
- if (built_in_decls[BUILT_IN_MEMMOVE] == NULL)
+ if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE))
local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE,
"memmove", ECF_NOTHROW | ECF_LEAF);
}
- if (built_in_decls[BUILT_IN_MEMCMP] == NULL)
+ if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP))
{
ftype = build_function_type_list (integer_type_node, const_ptr_type_node,
const_ptr_type_node, size_type_node,
@@ -9466,7 +9464,7 @@ build_common_builtin_nodes (void)
"memcmp", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
}
- if (built_in_decls[BUILT_IN_MEMSET] == NULL)
+ if (!builtin_decl_explicit_p (BUILT_IN_MEMSET))
{
ftype = build_function_type_list (ptr_type_node,
ptr_type_node, integer_type_node,
@@ -9475,7 +9473,7 @@ build_common_builtin_nodes (void)
"memset", ECF_NOTHROW | ECF_LEAF);
}
- if (built_in_decls[BUILT_IN_ALLOCA] == NULL)
+ if (!builtin_decl_explicit_p (BUILT_IN_ALLOCA))
{
ftype = build_function_type_list (ptr_type_node,
size_type_node, NULL_TREE);
@@ -9483,9 +9481,18 @@ build_common_builtin_nodes (void)
"alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
}
+ ftype = build_function_type_list (ptr_type_node, size_type_node,
+ size_type_node, NULL_TREE);
+ local_define_builtin ("__builtin_alloca_with_align", ftype,
+ BUILT_IN_ALLOCA_WITH_ALIGN, "alloca",
+ ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
+
/* If we're checking the stack, `alloca' can throw. */
if (flag_stack_check)
- TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0;
+ {
+ TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA)) = 0;
+ TREE_NOTHROW (builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN)) = 0;
+ }
ftype = build_function_type_list (void_type_node,
ptr_type_node, ptr_type_node,
@@ -9551,7 +9558,7 @@ build_common_builtin_nodes (void)
? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
ECF_NORETURN);
- if (built_in_decls[BUILT_IN_RETURN_ADDRESS] == NULL_TREE)
+ if (builtin_decl_explicit (BUILT_IN_RETURN_ADDRESS) == NULL_TREE)
{
ftype = build_function_type_list (ptr_type_node, integer_type_node,
NULL_TREE);
@@ -9561,16 +9568,16 @@ build_common_builtin_nodes (void)
ECF_NOTHROW);
}
- if (built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER] == NULL_TREE
- || built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT] == NULL_TREE)
+ if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_ENTER)
+ || !builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_EXIT))
{
ftype = build_function_type_list (void_type_node, ptr_type_node,
ptr_type_node, NULL_TREE);
- if (built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER] == NULL_TREE)
+ if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_ENTER))
local_define_builtin ("__cyg_profile_func_enter", ftype,
BUILT_IN_PROFILE_FUNC_ENTER,
"__cyg_profile_func_enter", 0);
- if (built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT] == NULL_TREE)
+ if (!builtin_decl_explicit_p (BUILT_IN_PROFILE_FUNC_EXIT))
local_define_builtin ("__cyg_profile_func_exit", ftype,
BUILT_IN_PROFILE_FUNC_EXIT,
"__cyg_profile_func_exit", 0);
diff --git a/gcc/tree.def b/gcc/tree.def
index ea255d5805d..1472cb15fb8 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -497,6 +497,20 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc_expression, 3)
*/
DEFTREECODE (VEC_COND_EXPR, "vec_cond_expr", tcc_expression, 3)
+/* Vector permutation expression. A = VEC_PERM_EXPR<v0, v1, mask> means
+
+ N = length(mask)
+ foreach i in N:
+ M = mask[i] % (2*N)
+ A = M < N ? v0[M] : v1[M-N]
+
+ V0 and V1 are vectors of the same type. MASK is an integer-typed
+ vector. The number of MASK elements must be the same with the
+ number of elements in V0 and V1. The size of the inner type
+ of the MASK and of the V0 and V1 must be the same.
+*/
+DEFTREECODE (VEC_PERM_EXPR, "vec_perm_expr", tcc_expression, 3)
+
/* Declare local variables, including making RTL and allocating space.
BIND_EXPR_VARS is a chain of VAR_DECL nodes for the variables.
BIND_EXPR_BODY is the body, the expression to be computed using
@@ -1111,6 +1125,19 @@ DEFTREECODE (WIDEN_MULT_PLUS_EXPR, "widen_mult_plus_expr", tcc_expression, 3)
is subtracted from t3. */
DEFTREECODE (WIDEN_MULT_MINUS_EXPR, "widen_mult_minus_expr", tcc_expression, 3)
+/* Widening shift left.
+ The first operand is of type t1.
+ The second operand is the number of bits to shift by; it need not be the
+ same type as the first operand and result.
+ Note that the result is undefined if the second operand is larger
+ than or equal to the first operand's type size.
+ The type of the entire expression is t2, such that t2 is at least twice
+ the size of t1.
+ WIDEN_LSHIFT_EXPR is equivalent to first widening (promoting)
+ the first argument from type t1 to type t2, and then shifting it
+ by the second argument. */
+DEFTREECODE (WIDEN_LSHIFT_EXPR, "widen_lshift_expr", tcc_binary, 2)
+
/* Fused multiply-add.
All operands and the result are of the same type. No intermediate
rounding is performed after multiplying operand one with operand two
@@ -1166,6 +1193,16 @@ DEFTREECODE (VEC_EXTRACT_ODD_EXPR, "vec_extractodd_expr", tcc_binary, 2)
DEFTREECODE (VEC_INTERLEAVE_HIGH_EXPR, "vec_interleavehigh_expr", tcc_binary, 2)
DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "vec_interleavelow_expr", tcc_binary, 2)
+/* Widening vector shift left in bits.
+ Operand 0 is a vector to be shifted with N elements of size S.
+ Operand 1 is an integer shift amount in bits.
+ The result of the operation is N elements of size 2*S.
+ VEC_WIDEN_LSHIFT_HI_EXPR computes the N/2 high results.
+ VEC_WIDEN_LSHIFT_LO_EXPR computes the N/2 low results.
+ */
+DEFTREECODE (VEC_WIDEN_LSHIFT_HI_EXPR, "widen_lshift_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_LSHIFT_LO_EXPR, "widen_lshift_lo_expr", tcc_binary, 2)
+
/* PREDICT_EXPR. Specify hint for branch prediction. The
PREDICT_EXPR_PREDICTOR specify predictor and PREDICT_EXPR_OUTCOME the
outcome (0 for not taken and 1 for taken). Once the profile is guessed
diff --git a/gcc/tree.h b/gcc/tree.h
index f064bbe30f5..64ccdb03417 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -335,10 +335,6 @@ extern const char * built_in_names[(int) END_BUILTINS];
#define CASE_FLT_FN(FN) case FN: case FN##F: case FN##L
#define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R
#define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL
-
-/* An array of _DECL trees for the above. */
-extern GTY(()) tree built_in_decls[(int) END_BUILTINS];
-extern GTY(()) tree implicit_built_in_decls[(int) END_BUILTINS];
/* In an OMP_CLAUSE node. */
@@ -2971,6 +2967,17 @@ extern void decl_value_expr_insert (tree, tree);
/* The DECL_RTL for NODE, if it is set, or NULL, if it is not set. */
#define DECL_RTL_IF_SET(NODE) (DECL_RTL_SET_P (NODE) ? DECL_RTL (NODE) : NULL)
+#if (GCC_VERSION >= 2007)
+#define DECL_RTL_KNOWN_SET(decl) __extension__ \
+({ tree const __d = (decl); \
+ gcc_checking_assert (DECL_RTL_SET_P (__d)); \
+ /* Dereference it so the compiler knows it can't be NULL even \
+ without assertion checking. */ \
+ &*DECL_RTL_IF_SET (__d); })
+#else
+#define DECL_RTL_KNOWN_SET(decl) (&*DECL_RTL_IF_SET (decl))
+#endif
+
/* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'. */
#define DECL_REGISTER(NODE) (DECL_WRTL_CHECK (NODE)->decl_common.decl_flag_0)
@@ -5352,6 +5359,7 @@ fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off)
fold_build_pointer_plus_hwi_loc (UNKNOWN_LOCATION, p, o)
/* In builtins.c */
+extern bool avoid_folding_inline_builtin (tree);
extern tree fold_call_expr (location_t, tree, bool);
extern tree fold_builtin_fputs (location_t, tree, tree, bool, bool, tree);
extern tree fold_builtin_strcpy (location_t, tree, tree, tree, tree);
@@ -5776,6 +5784,7 @@ tree target_for_debug_bind (tree);
/* In tree-ssa-address.c. */
extern tree tree_mem_ref_addr (tree, tree);
extern void copy_mem_ref_info (tree, tree);
+extern void copy_ref_info (tree, tree);
/* In tree-vrp.c */
extern bool ssa_name_nonnegative_p (const_tree);
@@ -5916,4 +5925,94 @@ is_lang_specific (tree t)
/* In gimple-low.c. */
extern bool block_may_fallthru (const_tree);
+
+/* Functional interface to the builtin functions. */
+
+/* The builtin_info structure holds the FUNCTION_DECL of the standard builtin
+ function, and a flag that says if the function is available implicitly, or
+ whether the user has to code explicit calls to __builtin_<xxx>. */
+
+typedef struct GTY(()) builtin_info_type_d {
+ tree decl[(int)END_BUILTINS];
+ bool implicit_p[(int)END_BUILTINS];
+} builtin_info_type;
+
+extern GTY(()) builtin_info_type builtin_info;
+
+/* Valid builtin number. */
+#define BUILTIN_VALID_P(FNCODE) \
+ (IN_RANGE ((int)FNCODE, ((int)BUILT_IN_NONE) + 1, ((int) END_BUILTINS) - 1))
+
+/* Return the tree node for an explicit standard builtin function or NULL. */
+static inline tree
+builtin_decl_explicit (enum built_in_function fncode)
+{
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+
+ return builtin_info.decl[(size_t)fncode];
+}
+
+/* Return the tree node for an implicit builtin function or NULL. */
+static inline tree
+builtin_decl_implicit (enum built_in_function fncode)
+{
+ size_t uns_fncode = (size_t)fncode;
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+
+ if (!builtin_info.implicit_p[uns_fncode])
+ return NULL_TREE;
+
+ return builtin_info.decl[uns_fncode];
+}
+
+/* Set explicit builtin function nodes and whether it is an implicit
+ function. */
+
+static inline void
+set_builtin_decl (enum built_in_function fncode, tree decl, bool implicit_p)
+{
+ size_t ufncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode)
+ && (decl != NULL_TREE || !implicit_p));
+
+ builtin_info.decl[ufncode] = decl;
+ builtin_info.implicit_p[ufncode] = implicit_p;
+}
+
+/* Set the implicit flag for a builtin function. */
+
+static inline void
+set_builtin_decl_implicit_p (enum built_in_function fncode, bool implicit_p)
+{
+ size_t uns_fncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode)
+ && builtin_info.decl[uns_fncode] != NULL_TREE);
+
+ builtin_info.implicit_p[uns_fncode] = implicit_p;
+}
+
+/* Return whether the standard builtin function can be used as an explicit
+ function. */
+
+static inline bool
+builtin_decl_explicit_p (enum built_in_function fncode)
+{
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+ return (builtin_info.decl[(size_t)fncode] != NULL_TREE);
+}
+
+/* Return whether the standard builtin function can be used implicitly. */
+
+static inline bool
+builtin_decl_implicit_p (enum built_in_function fncode)
+{
+ size_t uns_fncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+ return (builtin_info.decl[uns_fncode] != NULL_TREE
+ && builtin_info.implicit_p[uns_fncode]);
+}
+
#endif /* GCC_TREE_H */
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 214f58a8ac2..8a64000b616 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -301,6 +301,48 @@ typedef struct location_chain_def
enum var_init_status init;
} *location_chain;
+/* A vector of loc_exp_dep holds the active dependencies of a one-part
+ DV on VALUEs, i.e., the VALUEs expanded so as to form the current
+ location of DV. Each entry is also part of VALUE' s linked-list of
+ backlinks back to DV. */
+typedef struct loc_exp_dep_s
+{
+ /* The dependent DV. */
+ decl_or_value dv;
+ /* The dependency VALUE or DECL_DEBUG. */
+ rtx value;
+ /* The next entry in VALUE's backlinks list. */
+ struct loc_exp_dep_s *next;
+ /* A pointer to the pointer to this entry (head or prev's next) in
+ the doubly-linked list. */
+ struct loc_exp_dep_s **pprev;
+} loc_exp_dep;
+
+DEF_VEC_O (loc_exp_dep);
+
+/* This data structure is allocated for one-part variables at the time
+ of emitting notes. */
+struct onepart_aux
+{
+ /* Doubly-linked list of dependent DVs. These are DVs whose cur_loc
+ computation used the expansion of this variable, and that ought
+ to be notified should this variable change. If the DV's cur_loc
+ expanded to NULL, all components of the loc list are regarded as
+ active, so that any changes in them give us a chance to get a
+ location. Otherwise, only components of the loc that expanded to
+ non-NULL are regarded as active dependencies. */
+ loc_exp_dep *backlinks;
+ /* This holds the LOC that was expanded into cur_loc. We need only
+ mark a one-part variable as changed if the FROM loc is removed,
+ or if it has no known location and a loc is added, or if it gets
+ a change notification from any of its active dependencies. */
+ rtx from;
+ /* The depth of the cur_loc expression. */
+ int depth;
+ /* Dependencies actively used when expand FROM into cur_loc. */
+ VEC (loc_exp_dep, none) deps;
+};
+
/* Structure describing one part of variable. */
typedef struct variable_part_def
{
@@ -310,13 +352,33 @@ typedef struct variable_part_def
/* Location which was last emitted to location list. */
rtx cur_loc;
- /* The offset in the variable. */
- HOST_WIDE_INT offset;
+ union variable_aux
+ {
+ /* The offset in the variable, if !var->onepart. */
+ HOST_WIDE_INT offset;
+
+ /* Pointer to auxiliary data, if var->onepart and emit_notes. */
+ struct onepart_aux *onepaux;
+ } aux;
} variable_part;
/* Maximum number of location parts. */
#define MAX_VAR_PARTS 16
+/* Enumeration type used to discriminate various types of one-part
+ variables. */
+typedef enum onepart_enum
+{
+ /* Not a one-part variable. */
+ NOT_ONEPART = 0,
+ /* A one-part DECL that is not a DEBUG_EXPR_DECL. */
+ ONEPART_VDECL = 1,
+ /* A DEBUG_EXPR_DECL. */
+ ONEPART_DEXPR = 2,
+ /* A VALUE. */
+ ONEPART_VALUE = 3
+} onepart_enum_t;
+
/* Structure describing where the variable is located. */
typedef struct variable_def
{
@@ -330,10 +392,8 @@ typedef struct variable_def
/* Number of variable parts. */
char n_var_parts;
- /* True if this variable changed (any of its) cur_loc fields
- during the current emit_notes_for_changes resp.
- emit_notes_for_differences call. */
- bool cur_loc_changed;
+ /* What type of DV this is, according to enum onepart_enum. */
+ ENUM_BITFIELD (onepart_enum) onepart : CHAR_BIT;
/* True if this variable_def struct is currently in the
changed_variables hash table. */
@@ -344,29 +404,48 @@ typedef struct variable_def
} *variable;
typedef const struct variable_def *const_variable;
-/* Structure for chaining backlinks from referenced VALUEs to
- DVs that are referencing them. */
-typedef struct value_chain_def
-{
- /* Next value_chain entry. */
- struct value_chain_def *next;
-
- /* The declaration of the variable, or an RTL value
- being handled like a declaration, whose var_parts[0].loc_chain
- references the VALUE owning this value_chain. */
- decl_or_value dv;
-
- /* Reference count. */
- int refcount;
-} *value_chain;
-typedef const struct value_chain_def *const_value_chain;
-
/* Pointer to the BB's information specific to variable tracking pass. */
#define VTI(BB) ((variable_tracking_info) (BB)->aux)
/* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
+#if ENABLE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Access VAR's Ith part's offset, checking that it's not a one-part
+ variable. */
+#define VAR_PART_OFFSET(var, i) __extension__ \
+(*({ variable const __v = (var); \
+ gcc_checking_assert (!__v->onepart); \
+ &__v->var_part[(i)].aux.offset; }))
+
+/* Access VAR's one-part auxiliary data, checking that it is a
+ one-part variable. */
+#define VAR_LOC_1PAUX(var) __extension__ \
+(*({ variable const __v = (var); \
+ gcc_checking_assert (__v->onepart); \
+ &__v->var_part[0].aux.onepaux; }))
+
+#else
+#define VAR_PART_OFFSET(var, i) ((var)->var_part[(i)].aux.offset)
+#define VAR_LOC_1PAUX(var) ((var)->var_part[0].aux.onepaux)
+#endif
+
+/* These are accessor macros for the one-part auxiliary data. When
+ convenient for users, they're guarded by tests that the data was
+ allocated. */
+#define VAR_LOC_DEP_LST(var) (VAR_LOC_1PAUX (var) \
+ ? VAR_LOC_1PAUX (var)->backlinks \
+ : NULL)
+#define VAR_LOC_DEP_LSTP(var) (VAR_LOC_1PAUX (var) \
+ ? &VAR_LOC_1PAUX (var)->backlinks \
+ : NULL)
+#define VAR_LOC_FROM(var) (VAR_LOC_1PAUX (var)->from)
+#define VAR_LOC_DEPTH(var) (VAR_LOC_1PAUX (var)->depth)
+#define VAR_LOC_DEP_VEC(var) (VAR_LOC_1PAUX (var) \
+ ? &VAR_LOC_1PAUX (var)->deps \
+ : NULL)
+
/* Alloc pool for struct attrs_def. */
static alloc_pool attrs_pool;
@@ -382,24 +461,24 @@ static alloc_pool loc_chain_pool;
/* Alloc pool for struct shared_hash_def. */
static alloc_pool shared_hash_pool;
-/* Alloc pool for struct value_chain_def. */
-static alloc_pool value_chain_pool;
-
/* Changed variables, notes will be emitted for them. */
static htab_t changed_variables;
-/* Links from VALUEs to DVs referencing them in their current loc_chains. */
-static htab_t value_chains;
-
/* Shall notes be emitted? */
static bool emit_notes;
+/* Values whose dynamic location lists have gone empty, but whose
+ cselib location lists are still usable. Use this to hold the
+ current location, the backlinks, etc, during emit_notes. */
+static htab_t dropped_values;
+
/* Empty shared hashtable. */
static shared_hash empty_shared_hash;
/* Scratch register bitmap used by cselib_expand_value_rtx. */
static bitmap scratch_regs = NULL;
+#ifdef HAVE_window_save
typedef struct GTY(()) parm_reg {
rtx outgoing;
rtx incoming;
@@ -410,6 +489,7 @@ DEF_VEC_ALLOC_O(parm_reg_t, gc);
/* Vector of windowed parameter registers, if any. */
static VEC(parm_reg_t, gc) *windowed_parm_regs = NULL;
+#endif
/* Variable used to tell whether cselib_process_insn called our hook. */
static bool cselib_hook_called;
@@ -420,7 +500,6 @@ static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
HOST_WIDE_INT *);
static bool vt_stack_adjustments (void);
-static void note_register_arguments (rtx);
static hashval_t variable_htab_hash (const void *);
static int variable_htab_eq (const void *, const void *);
static void variable_htab_free (void *);
@@ -476,6 +555,7 @@ static void dump_vars (htab_t);
static void dump_dataflow_set (dataflow_set *);
static void dump_dataflow_sets (void);
+static void set_dv_changed (decl_or_value, bool);
static void variable_was_changed (variable, dataflow_set *);
static void **set_slot_part (dataflow_set *, rtx, void **,
decl_or_value, HOST_WIDE_INT,
@@ -672,15 +752,11 @@ vt_stack_adjustments (void)
for (insn = BB_HEAD (dest);
insn != NEXT_INSN (BB_END (dest));
insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- {
- insn_stack_adjust_offset_pre_post (insn, &pre, &post);
- offset += pre + post;
- }
- if (CALL_P (insn))
- note_register_arguments (insn);
- }
+ if (INSN_P (insn))
+ {
+ insn_stack_adjust_offset_pre_post (insn, &pre, &post);
+ offset += pre + post;
+ }
VTI (dest)->out.stack_adjust = offset;
@@ -1133,6 +1209,21 @@ dv_as_value (decl_or_value dv)
return (rtx)dv;
}
+/* Return the DEBUG_EXPR of a DEBUG_EXPR_DECL or the VALUE in DV. */
+static inline rtx
+dv_as_rtx (decl_or_value dv)
+{
+ tree decl;
+
+ if (dv_is_value_p (dv))
+ return dv_as_value (dv);
+
+ decl = dv_as_decl (dv);
+
+ gcc_checking_assert (TREE_CODE (decl) == DEBUG_EXPR_DECL);
+ return DECL_RTL_KNOWN_SET (decl);
+}
+
/* Return the opaque pointer in the decl_or_value. */
static inline void *
dv_as_opaque (decl_or_value dv)
@@ -1140,36 +1231,36 @@ dv_as_opaque (decl_or_value dv)
return dv;
}
-/* Return true if a decl_or_value must not have more than one variable
- part. */
-static inline bool
+/* Return nonzero if a decl_or_value must not have more than one
+ variable part. The returned value discriminates among various
+ kinds of one-part DVs ccording to enum onepart_enum. */
+static inline onepart_enum_t
dv_onepart_p (decl_or_value dv)
{
tree decl;
if (!MAY_HAVE_DEBUG_INSNS)
- return false;
+ return NOT_ONEPART;
if (dv_is_value_p (dv))
- return true;
+ return ONEPART_VALUE;
decl = dv_as_decl (dv);
- if (!decl)
- return true;
-
if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
- return true;
+ return ONEPART_DEXPR;
- return (target_for_debug_bind (decl) != NULL_TREE);
+ if (target_for_debug_bind (decl) != NULL_TREE)
+ return ONEPART_VDECL;
+
+ return NOT_ONEPART;
}
-/* Return the variable pool to be used for dv, depending on whether it
- can have multiple parts or not. */
+/* Return the variable pool to be used for a dv of type ONEPART. */
static inline alloc_pool
-dv_pool (decl_or_value dv)
+onepart_pool (onepart_enum_t onepart)
{
- return dv_onepart_p (dv) ? valvar_pool : var_pool;
+ return onepart ? valvar_pool : var_pool;
}
/* Build a decl_or_value out of a decl. */
@@ -1192,6 +1283,30 @@ dv_from_value (rtx value)
return dv;
}
+/* Return a value or the decl of a debug_expr as a decl_or_value. */
+static inline decl_or_value
+dv_from_rtx (rtx x)
+{
+ decl_or_value dv;
+
+ switch (GET_CODE (x))
+ {
+ case DEBUG_EXPR:
+ dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
+ gcc_checking_assert (DECL_RTL_KNOWN_SET (DEBUG_EXPR_TREE_DECL (x)) == x);
+ break;
+
+ case VALUE:
+ dv = dv_from_value (x);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return dv;
+}
+
extern void debug_dv (decl_or_value dv);
DEBUG_FUNCTION void
@@ -1254,6 +1369,8 @@ variable_htab_eq (const void *x, const void *y)
return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
}
+static void loc_exp_dep_clear (variable var);
+
/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
static void
@@ -1278,29 +1395,18 @@ variable_htab_free (void *elem)
}
var->var_part[i].loc_chain = NULL;
}
- pool_free (dv_pool (var->dv), var);
-}
-
-/* The hash function for value_chains htab, computes the hash value
- from the VALUE. */
-
-static hashval_t
-value_chain_htab_hash (const void *x)
-{
- const_value_chain const v = (const_value_chain) x;
-
- return dv_htab_hash (v->dv);
-}
-
-/* Compare the VALUE X with VALUE Y. */
-
-static int
-value_chain_htab_eq (const void *x, const void *y)
-{
- const_value_chain const v = (const_value_chain) x;
- decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
-
- return dv_as_opaque (v->dv) == dv_as_opaque (dv);
+ if (var->onepart && VAR_LOC_1PAUX (var))
+ {
+ loc_exp_dep_clear (var);
+ if (VAR_LOC_DEP_LST (var))
+ VAR_LOC_DEP_LST (var)->pprev = NULL;
+ XDELETE (VAR_LOC_1PAUX (var));
+ /* These may be reused across functions, so reset
+ e.g. NO_LOC_P. */
+ if (var->onepart == ONEPART_DEXPR)
+ set_dv_changed (var->dv, true);
+ }
+ pool_free (onepart_pool (var->onepart), var);
}
/* Initialize the set (array) SET of attrs to empty lists. */
@@ -1569,13 +1675,12 @@ unshare_variable (dataflow_set *set, void **slot, variable var,
variable new_var;
int i;
- new_var = (variable) pool_alloc (dv_pool (var->dv));
+ new_var = (variable) pool_alloc (onepart_pool (var->onepart));
new_var->dv = var->dv;
new_var->refcount = 1;
var->refcount--;
new_var->n_var_parts = var->n_var_parts;
- new_var->cur_loc_changed = var->cur_loc_changed;
- var->cur_loc_changed = false;
+ new_var->onepart = var->onepart;
new_var->in_changed_variables = false;
if (! flag_var_tracking_uninit)
@@ -1586,7 +1691,18 @@ unshare_variable (dataflow_set *set, void **slot, variable var,
location_chain node;
location_chain *nextp;
- new_var->var_part[i].offset = var->var_part[i].offset;
+ if (i == 0 && var->onepart)
+ {
+ /* One-part auxiliary data is only used while emitting
+ notes, so propagate it to the new variable in the active
+ dataflow set. If we're not emitting notes, this will be
+ a no-op. */
+ gcc_checking_assert (!VAR_LOC_1PAUX (var) || emit_notes);
+ VAR_LOC_1PAUX (new_var) = VAR_LOC_1PAUX (var);
+ VAR_LOC_1PAUX (var) = NULL;
+ }
+ else
+ VAR_PART_OFFSET (new_var, i) = VAR_PART_OFFSET (var, i);
nextp = &new_var->var_part[i].loc_chain;
for (node = var->var_part[i].loc_chain; node; node = node->next)
{
@@ -1891,6 +2007,26 @@ var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
delete_variable_part (set, loc, dv_from_decl (decl), offset);
}
+/* Return true if LOC should not be expanded for location expressions,
+ or used in them. */
+
+static inline bool
+unsuitable_loc (rtx loc)
+{
+ switch (GET_CODE (loc))
+ {
+ case PC:
+ case SCRATCH:
+ case CC0:
+ case ASM_INPUT:
+ case ASM_OPERANDS:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/* Bind a value to a location it was just stored in. If MODIFIED
holds, assume the location was modified, detaching it from any
values bound to it. */
@@ -1904,10 +2040,10 @@ val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
if (dump_file)
{
- fprintf (dump_file, "%i: ", INSN_UID (insn));
- print_inline_rtx (dump_file, val, 0);
- fprintf (dump_file, " stored in ");
+ fprintf (dump_file, "%i: ", insn ? INSN_UID (insn) : 0);
print_inline_rtx (dump_file, loc, 0);
+ fprintf (dump_file, " evaluates to ");
+ print_inline_rtx (dump_file, val, 0);
if (v->locs)
{
struct elt_loc_list *l;
@@ -1920,6 +2056,8 @@ val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
fprintf (dump_file, "\n");
}
+ gcc_checking_assert (!unsuitable_loc (loc));
+
if (REG_P (loc))
{
if (modified)
@@ -1931,6 +2069,8 @@ val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
dv_from_value (val), 0, NULL_RTX, INSERT);
else
+ /* ??? Ideally we wouldn't get these, and use them from the static
+ cselib loc list. */
set_variable_part (set, loc, dv_from_value (val), 0,
VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
}
@@ -1997,13 +2137,6 @@ val_reset (dataflow_set *set, decl_or_value dv)
delete_variable_part (set, dv_as_value (dv), dv_from_value (cval), 0);
clobber_variable_part (set, NULL, dv, 0, NULL);
-
- /* ??? Should we make sure there aren't other available values or
- variables whose values involve this one other than by
- equivalence? E.g., at the very least we should reset MEMs, those
- shouldn't be too hard to find cselib-looking up the value as an
- address, then locating the resulting value in our own hash
- table. */
}
/* Find the values in a given location and map the val to another
@@ -2029,6 +2162,8 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
val_reset (set, dv);
+ gcc_checking_assert (!unsuitable_loc (loc));
+
if (REG_P (loc))
{
attrs node, found = NULL;
@@ -2061,6 +2196,8 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
dv_from_value (val), 0, NULL_RTX, INSERT);
else
+ /* ??? Ideally we wouldn't get these, and use them from the static
+ cselib loc list. */
/* ??? Merge equivalent expressions. */
set_variable_part (set, loc, dv_from_value (val), 0,
VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
@@ -2176,10 +2313,11 @@ variable_union (variable src, dataflow_set *set)
dst = (variable) *dstp;
gcc_assert (src->n_var_parts);
+ gcc_checking_assert (src->onepart == dst->onepart);
/* We can combine one-part variables very efficiently, because their
entries are in canonical order. */
- if (dv_onepart_p (src->dv))
+ if (src->onepart)
{
location_chain *nodep, dnode, snode;
@@ -2233,16 +2371,18 @@ variable_union (variable src, dataflow_set *set)
return 1;
}
+ gcc_checking_assert (!src->onepart);
+
/* Count the number of location parts, result is K. */
for (i = 0, j = 0, k = 0;
i < src->n_var_parts && j < dst->n_var_parts; k++)
{
- if (src->var_part[i].offset == dst->var_part[j].offset)
+ if (VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
{
i++;
j++;
}
- else if (src->var_part[i].offset < dst->var_part[j].offset)
+ else if (VAR_PART_OFFSET (src, i) < VAR_PART_OFFSET (dst, j))
i++;
else
j++;
@@ -2252,7 +2392,7 @@ variable_union (variable src, dataflow_set *set)
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
thus there are at most MAX_VAR_PARTS different offsets. */
- gcc_assert (dv_onepart_p (dst->dv) ? k == 1 : k <= MAX_VAR_PARTS);
+ gcc_checking_assert (dst->onepart ? k == 1 : k <= MAX_VAR_PARTS);
if (dst->n_var_parts != k && shared_var_p (dst, set->vars))
{
@@ -2269,7 +2409,7 @@ variable_union (variable src, dataflow_set *set)
location_chain node, node2;
if (i >= 0 && j >= 0
- && src->var_part[i].offset == dst->var_part[j].offset)
+ && VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
{
/* Compute the "sorted" union of the chains, i.e. the locations which
are in both chains go first, they are sorted by the sum of
@@ -2317,7 +2457,7 @@ variable_union (variable src, dataflow_set *set)
/* The most common case, much simpler, no qsort is needed. */
location_chain dstnode = dst->var_part[j].loc_chain;
dst->var_part[k].loc_chain = dstnode;
- dst->var_part[k].offset = dst->var_part[j].offset;
+ VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET(dst, j);
node2 = dstnode;
for (node = src->var_part[i].loc_chain; node; node = node->next)
if (!((REG_P (dstnode->loc)
@@ -2455,20 +2595,20 @@ variable_union (variable src, dataflow_set *set)
dst->var_part[k].loc_chain = vui[0].lc;
}
- dst->var_part[k].offset = dst->var_part[j].offset;
+ VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (dst, j);
}
i--;
j--;
}
else if ((i >= 0 && j >= 0
- && src->var_part[i].offset < dst->var_part[j].offset)
+ && VAR_PART_OFFSET (src, i) < VAR_PART_OFFSET (dst, j))
|| i < 0)
{
dst->var_part[k] = dst->var_part[j];
j--;
}
else if ((i >= 0 && j >= 0
- && src->var_part[i].offset > dst->var_part[j].offset)
+ && VAR_PART_OFFSET (src, i) > VAR_PART_OFFSET (dst, j))
|| j < 0)
{
location_chain *nextp;
@@ -2492,7 +2632,7 @@ variable_union (variable src, dataflow_set *set)
nextp = &new_lc->next;
}
- dst->var_part[k].offset = src->var_part[i].offset;
+ VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (src, i);
i--;
}
dst->var_part[k].cur_loc = NULL;
@@ -2543,25 +2683,46 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
/* Whether the value is currently being expanded. */
#define VALUE_RECURSED_INTO(x) \
(RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
-/* Whether the value is in changed_variables hash table. */
+
+/* Whether no expansion was found, saving useless lookups.
+ It must only be set when VALUE_CHANGED is clear. */
+#define NO_LOC_P(x) \
+ (RTL_FLAG_CHECK2 ("NO_LOC_P", (x), VALUE, DEBUG_EXPR)->return_val)
+
+/* Whether cur_loc in the value needs to be (re)computed. */
#define VALUE_CHANGED(x) \
(RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
-/* Whether the decl is in changed_variables hash table. */
+/* Whether cur_loc in the decl needs to be (re)computed. */
#define DECL_CHANGED(x) TREE_VISITED (x)
-/* Record that DV has been added into resp. removed from changed_variables
- hashtable. */
+/* Record (if NEWV) that DV needs to have its cur_loc recomputed. For
+ user DECLs, this means they're in changed_variables. Values and
+ debug exprs may be left with this flag set if no user variable
+ requires them to be evaluated. */
static inline void
set_dv_changed (decl_or_value dv, bool newv)
{
- if (dv_is_value_p (dv))
- VALUE_CHANGED (dv_as_value (dv)) = newv;
- else
- DECL_CHANGED (dv_as_decl (dv)) = newv;
+ switch (dv_onepart_p (dv))
+ {
+ case ONEPART_VALUE:
+ if (newv)
+ NO_LOC_P (dv_as_value (dv)) = false;
+ VALUE_CHANGED (dv_as_value (dv)) = newv;
+ break;
+
+ case ONEPART_DEXPR:
+ if (newv)
+ NO_LOC_P (DECL_RTL_KNOWN_SET (dv_as_decl (dv))) = false;
+ /* Fall through... */
+
+ default:
+ DECL_CHANGED (dv_as_decl (dv)) = newv;
+ break;
+ }
}
-/* Return true if DV is present in changed_variables hash table. */
+/* Return true if DV needs to have its cur_loc recomputed. */
static inline bool
dv_changed_p (decl_or_value dv)
@@ -2585,12 +2746,11 @@ find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
if (!var)
return NULL;
- gcc_checking_assert (dv_onepart_p (var->dv));
+ gcc_checking_assert (var->onepart);
if (!var->n_var_parts)
return NULL;
- gcc_checking_assert (var->var_part[0].offset == 0);
gcc_checking_assert (loc != dv_as_opaque (var->dv));
loc_code = GET_CODE (loc);
@@ -2639,6 +2799,8 @@ find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
return find_loc_in_1pdv (loc, rvar, vars);
}
+ /* ??? Gotta look in cselib_val locations too. */
+
return NULL;
}
@@ -2683,7 +2845,7 @@ insert_into_intersection (location_chain *nodep, rtx loc,
*nodep = node;
}
-/* Insert in DEST the intersection the locations present in both
+/* Insert in DEST the intersection of the locations present in both
S1NODE and S2VAR, directly or indirectly. S1NODE is from a
variable in DSM->cur, whereas S2VAR is from DSM->src. dvar is in
DSM->dst. */
@@ -2700,11 +2862,10 @@ intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
{
location_chain s2node;
- gcc_checking_assert (dv_onepart_p (s2var->dv));
+ gcc_checking_assert (s2var->onepart);
if (s2var->n_var_parts)
{
- gcc_checking_assert (s2var->var_part[0].offset == 0);
s2node = s2var->var_part[0].loc_chain;
for (; s1node && s2node;
@@ -2750,6 +2911,8 @@ intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
}
}
+ /* ??? gotta look in cselib_val locations too. */
+
/* ??? if the location is equivalent to any location in src,
searched recursively
@@ -2839,6 +3002,18 @@ loc_cmp (rtx x, rtx y)
if (GET_CODE (y) == VALUE)
return 1;
+ /* Entry value is the least preferable kind of expression. */
+ if (GET_CODE (x) == ENTRY_VALUE)
+ {
+ if (GET_CODE (y) != ENTRY_VALUE)
+ return 1;
+ gcc_assert (GET_MODE (x) == GET_MODE (y));
+ return loc_cmp (XEXP (x, 0), XEXP (y, 0));
+ }
+
+ if (GET_CODE (y) == ENTRY_VALUE)
+ return -1;
+
if (GET_CODE (x) == GET_CODE (y))
/* Compare operands below. */;
else if (GET_CODE (x) < GET_CODE (y))
@@ -2933,186 +3108,23 @@ loc_cmp (rtx x, rtx y)
return 0;
}
-/* If decl or value DVP refers to VALUE from *LOC, add backlinks
- from VALUE to DVP. */
-
-static int
-add_value_chain (rtx *loc, void *dvp)
-{
- decl_or_value dv, ldv;
- value_chain vc, nvc;
- void **slot;
-
- if (GET_CODE (*loc) == VALUE)
- ldv = dv_from_value (*loc);
- else if (GET_CODE (*loc) == DEBUG_EXPR)
- ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
- else
- return 0;
-
- if (dv_as_opaque (ldv) == dvp)
- return 0;
-
- dv = (decl_or_value) dvp;
- slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
- INSERT);
- if (!*slot)
- {
- vc = (value_chain) pool_alloc (value_chain_pool);
- vc->dv = ldv;
- vc->next = NULL;
- vc->refcount = 0;
- *slot = (void *) vc;
- }
- else
- {
- for (vc = ((value_chain) *slot)->next; vc; vc = vc->next)
- if (dv_as_opaque (vc->dv) == dv_as_opaque (dv))
- break;
- if (vc)
- {
- vc->refcount++;
- return 0;
- }
- }
- vc = (value_chain) *slot;
- nvc = (value_chain) pool_alloc (value_chain_pool);
- nvc->dv = dv;
- nvc->next = vc->next;
- nvc->refcount = 1;
- vc->next = nvc;
- return 0;
-}
-
-/* If decl or value DVP refers to VALUEs from within LOC, add backlinks
- from those VALUEs to DVP. */
-
-static void
-add_value_chains (decl_or_value dv, rtx loc)
-{
- if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
- {
- add_value_chain (&loc, dv_as_opaque (dv));
- return;
- }
- if (REG_P (loc))
- return;
- if (MEM_P (loc))
- loc = XEXP (loc, 0);
- for_each_rtx (&loc, add_value_chain, dv_as_opaque (dv));
-}
-
-/* If CSELIB_VAL_PTR of value DV refer to VALUEs, add backlinks from those
- VALUEs to DV. Add the same time get rid of ASM_OPERANDS from locs list,
- that is something we never can express in .debug_info and can prevent
- reverse ops from being used. */
-
-static void
-add_cselib_value_chains (decl_or_value dv)
-{
- struct elt_loc_list **l;
-
- for (l = &CSELIB_VAL_PTR (dv_as_value (dv))->locs; *l;)
- if (GET_CODE ((*l)->loc) == ASM_OPERANDS)
- *l = (*l)->next;
- else
- {
- for_each_rtx (&(*l)->loc, add_value_chain, dv_as_opaque (dv));
- l = &(*l)->next;
- }
-}
-
-/* If decl or value DVP refers to VALUE from *LOC, remove backlinks
- from VALUE to DVP. */
-
-static int
-remove_value_chain (rtx *loc, void *dvp)
-{
- decl_or_value dv, ldv;
- value_chain vc;
- void **slot;
-
- if (GET_CODE (*loc) == VALUE)
- ldv = dv_from_value (*loc);
- else if (GET_CODE (*loc) == DEBUG_EXPR)
- ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
- else
- return 0;
-
- if (dv_as_opaque (ldv) == dvp)
- return 0;
-
- dv = (decl_or_value) dvp;
- slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
- NO_INSERT);
- for (vc = (value_chain) *slot; vc->next; vc = vc->next)
- if (dv_as_opaque (vc->next->dv) == dv_as_opaque (dv))
- {
- value_chain dvc = vc->next;
- gcc_assert (dvc->refcount > 0);
- if (--dvc->refcount == 0)
- {
- vc->next = dvc->next;
- pool_free (value_chain_pool, dvc);
- if (vc->next == NULL && vc == (value_chain) *slot)
- {
- pool_free (value_chain_pool, vc);
- htab_clear_slot (value_chains, slot);
- }
- }
- return 0;
- }
- gcc_unreachable ();
-}
-
-/* If decl or value DVP refers to VALUEs from within LOC, remove backlinks
- from those VALUEs to DVP. */
-
-static void
-remove_value_chains (decl_or_value dv, rtx loc)
-{
- if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
- {
- remove_value_chain (&loc, dv_as_opaque (dv));
- return;
- }
- if (REG_P (loc))
- return;
- if (MEM_P (loc))
- loc = XEXP (loc, 0);
- for_each_rtx (&loc, remove_value_chain, dv_as_opaque (dv));
-}
-
#if ENABLE_CHECKING
-/* If CSELIB_VAL_PTR of value DV refer to VALUEs, remove backlinks from those
- VALUEs to DV. */
-
-static void
-remove_cselib_value_chains (decl_or_value dv)
-{
- struct elt_loc_list *l;
-
- for (l = CSELIB_VAL_PTR (dv_as_value (dv))->locs; l; l = l->next)
- for_each_rtx (&l->loc, remove_value_chain, dv_as_opaque (dv));
-}
-
/* Check the order of entries in one-part variables. */
static int
canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED)
{
variable var = (variable) *slot;
- decl_or_value dv = var->dv;
location_chain node, next;
#ifdef ENABLE_RTL_CHECKING
int i;
for (i = 0; i < var->n_var_parts; i++)
gcc_assert (var->var_part[0].cur_loc == NULL);
- gcc_assert (!var->cur_loc_changed && !var->in_changed_variables);
+ gcc_assert (!var->in_changed_variables);
#endif
- if (!dv_onepart_p (dv))
+ if (!var->onepart)
return 1;
gcc_assert (var->n_var_parts == 1);
@@ -3186,7 +3198,7 @@ canonicalize_values_star (void **slot, void *data)
bool has_value;
bool has_marks;
- if (!dv_onepart_p (dv))
+ if (!var->onepart)
return 1;
gcc_checking_assert (var->n_var_parts == 1);
@@ -3408,7 +3420,7 @@ canonicalize_vars_star (void **slot, void *data)
variable cvar;
location_chain cnode;
- if (!dv_onepart_p (dv) || dv_is_value_p (dv))
+ if (!var->onepart || var->onepart == ONEPART_VALUE)
return 1;
gcc_assert (var->n_var_parts == 1);
@@ -3461,7 +3473,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
void **dstslot;
variable s2var, dvar = NULL;
decl_or_value dv = s1var->dv;
- bool onepart = dv_onepart_p (dv);
+ onepart_enum_t onepart = s1var->onepart;
rtx val;
hashval_t dvhash;
location_chain node, *nodep;
@@ -3475,8 +3487,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
if (!onepart)
return variable_union (s1var, dst);
- gcc_checking_assert (s1var->n_var_parts == 1
- && s1var->var_part[0].offset == 0);
+ gcc_checking_assert (s1var->n_var_parts == 1);
dvhash = dv_htab_hash (dv);
if (dv_is_value_p (dv))
@@ -3493,16 +3504,16 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
dsm->src_onepart_cnt--;
gcc_assert (s2var->var_part[0].loc_chain
- && s2var->n_var_parts == 1
- && s2var->var_part[0].offset == 0);
+ && s2var->onepart == onepart
+ && s2var->n_var_parts == 1);
dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
if (dstslot)
{
dvar = (variable)*dstslot;
gcc_assert (dvar->refcount == 1
- && dvar->n_var_parts == 1
- && dvar->var_part[0].offset == 0);
+ && dvar->onepart == onepart
+ && dvar->n_var_parts == 1);
nodep = &dvar->var_part[0].loc_chain;
}
else
@@ -3529,15 +3540,18 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
{
if (node)
{
- dvar = (variable) pool_alloc (dv_pool (dv));
+ dvar = (variable) pool_alloc (onepart_pool (onepart));
dvar->dv = dv;
dvar->refcount = 1;
dvar->n_var_parts = 1;
- dvar->cur_loc_changed = false;
+ dvar->onepart = onepart;
dvar->in_changed_variables = false;
- dvar->var_part[0].offset = 0;
dvar->var_part[0].loc_chain = node;
dvar->var_part[0].cur_loc = NULL;
+ if (onepart)
+ VAR_LOC_1PAUX (dvar) = NULL;
+ else
+ VAR_PART_OFFSET (dvar, 0) = 0;
dstslot
= shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash,
@@ -3662,15 +3676,16 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
INSERT);
if (!*slot)
{
- variable var = (variable) pool_alloc (dv_pool (dv));
+ variable var = (variable) pool_alloc (onepart_pool
+ (ONEPART_VALUE));
var->dv = dv;
var->refcount = 1;
var->n_var_parts = 1;
- var->cur_loc_changed = false;
+ var->onepart = ONEPART_VALUE;
var->in_changed_variables = false;
- var->var_part[0].offset = 0;
var->var_part[0].loc_chain = NULL;
var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (var) = NULL;
*slot = var;
}
@@ -3717,9 +3732,8 @@ variable_merge_over_src (variable s2var, struct dfset_merge *dsm)
{
dataflow_set *dst = dsm->dst;
decl_or_value dv = s2var->dv;
- bool onepart = dv_onepart_p (dv);
- if (!onepart)
+ if (!s2var->onepart)
{
void **dstp = shared_hash_find_slot (dst->vars, dv);
*dstp = s2var;
@@ -3864,7 +3878,7 @@ remove_duplicate_values (variable var)
{
location_chain node, *nodep;
- gcc_assert (dv_onepart_p (var->dv));
+ gcc_assert (var->onepart);
gcc_assert (var->n_var_parts == 1);
gcc_assert (var->refcount == 1);
@@ -3915,7 +3929,7 @@ variable_post_merge_new_vals (void **slot, void *info)
variable var = (variable)*slot;
location_chain node;
- if (!dv_onepart_p (var->dv) || !var->n_var_parts)
+ if (!var->onepart || !var->n_var_parts)
return 1;
gcc_assert (var->n_var_parts == 1);
@@ -4146,13 +4160,11 @@ find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars)
if (!var)
return NULL;
- gcc_assert (dv_onepart_p (var->dv));
+ gcc_assert (var->onepart);
if (!var->n_var_parts)
return NULL;
- gcc_assert (var->var_part[0].offset == 0);
-
VALUE_RECURSED_INTO (val) = true;
for (node = var->var_part[0].loc_chain; node; node = node->next)
@@ -4206,7 +4218,7 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
dataflow_set *set = (dataflow_set *) data;
variable var = (variable) *slot;
- if (dv_is_decl_p (var->dv) && dv_onepart_p (var->dv))
+ if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
{
tree decl = dv_as_decl (var->dv);
location_chain loc, *locp;
@@ -4277,10 +4289,7 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
{
changed = true;
var->var_part[0].cur_loc = NULL;
- var->cur_loc_changed = true;
}
- add_value_chains (var->dv, loc->loc);
- remove_value_chains (var->dv, old_loc);
}
locp = &loc->next;
continue;
@@ -4288,12 +4297,10 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
if (emit_notes)
{
- remove_value_chains (var->dv, old_loc);
if (old_loc == var->var_part[0].cur_loc)
{
changed = true;
var->var_part[0].cur_loc = NULL;
- var->cur_loc_changed = true;
}
}
*locp = loc->next;
@@ -4321,10 +4328,11 @@ dataflow_set_remove_mem_locs (void **slot, void *data)
dataflow_set *set = (dataflow_set *) data;
variable var = (variable) *slot;
- if (dv_is_value_p (var->dv))
+ if (var->onepart == ONEPART_VALUE)
{
location_chain loc, *locp;
bool changed = false;
+ rtx cur_loc;
gcc_assert (var->n_var_parts == 1);
@@ -4343,6 +4351,11 @@ dataflow_set_remove_mem_locs (void **slot, void *data)
gcc_assert (var->n_var_parts == 1);
}
+ if (VAR_LOC_1PAUX (var))
+ cur_loc = VAR_LOC_FROM (var);
+ else
+ cur_loc = var->var_part[0].cur_loc;
+
for (locp = &var->var_part[0].loc_chain, loc = *locp;
loc; loc = *locp)
{
@@ -4353,17 +4366,16 @@ dataflow_set_remove_mem_locs (void **slot, void *data)
continue;
}
- if (emit_notes)
- remove_value_chains (var->dv, loc->loc);
*locp = loc->next;
/* If we have deleted the location which was last emitted
we have to emit new location so add the variable to set
of changed variables. */
- if (var->var_part[0].cur_loc == loc->loc)
+ if (cur_loc == loc->loc)
{
changed = true;
var->var_part[0].cur_loc = NULL;
- var->cur_loc_changed = true;
+ if (VAR_LOC_1PAUX (var))
+ VAR_LOC_FROM (var) = NULL;
}
pool_free (loc_chain_pool, loc);
}
@@ -4467,20 +4479,24 @@ variable_different_p (variable var1, variable var2)
if (var1 == var2)
return false;
+ if (var1->onepart != var2->onepart)
+ return true;
+
if (var1->n_var_parts != var2->n_var_parts)
return true;
+ if (var1->onepart && var1->n_var_parts)
+ {
+ gcc_checking_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv)
+ && var1->n_var_parts == 1);
+ /* One-part values have locations in a canonical order. */
+ return onepart_variable_different_p (var1, var2);
+ }
+
for (i = 0; i < var1->n_var_parts; i++)
{
- if (var1->var_part[i].offset != var2->var_part[i].offset)
+ if (VAR_PART_OFFSET (var1, i) != VAR_PART_OFFSET (var2, i))
return true;
- /* One-part values have locations in a canonical order. */
- if (i == 0 && var1->var_part[i].offset == 0 && dv_onepart_p (var1->dv))
- {
- gcc_assert (var1->n_var_parts == 1
- && dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
- return onepart_variable_different_p (var1, var2);
- }
if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
return true;
if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
@@ -5020,9 +5036,6 @@ log_op_type (rtx x, basic_block bb, rtx insn,
/* All preserved VALUEs. */
static VEC (rtx, heap) *preserved_values;
-/* Registers used in the current function for passing parameters. */
-static HARD_REG_SET argument_reg_set;
-
/* Ensure VAL is preserved and remember it in a vector for vt_emit_notes. */
static void
@@ -5089,11 +5102,7 @@ add_uses (rtx *ploc, void *data)
if (MEM_P (vloc)
&& !REG_P (XEXP (vloc, 0))
- && !MEM_P (XEXP (vloc, 0))
- && GET_CODE (XEXP (vloc, 0)) != ENTRY_VALUE
- && (GET_CODE (XEXP (vloc, 0)) != PLUS
- || XEXP (XEXP (vloc, 0), 0) != cfa_base_rtx
- || !CONST_INT_P (XEXP (XEXP (vloc, 0), 1))))
+ && !MEM_P (XEXP (vloc, 0)))
{
rtx mloc = vloc;
enum machine_mode address_mode = get_address_mode (mloc);
@@ -5105,16 +5114,24 @@ add_uses (rtx *ploc, void *data)
{
micro_operation moa;
preserve_value (val);
- mloc = cselib_subst_to_values (XEXP (mloc, 0),
- GET_MODE (mloc));
- moa.type = MO_VAL_USE;
- moa.insn = cui->insn;
- moa.u.loc = gen_rtx_CONCAT (address_mode,
- val->val_rtx, mloc);
- if (dump_file && (dump_flags & TDF_DETAILS))
- log_op_type (moa.u.loc, cui->bb, cui->insn,
- moa.type, dump_file);
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
+
+ if (GET_CODE (XEXP (mloc, 0)) != ENTRY_VALUE
+ && (GET_CODE (XEXP (mloc, 0)) != PLUS
+ || XEXP (XEXP (mloc, 0), 0) != cfa_base_rtx
+ || !CONST_INT_P (XEXP (XEXP (mloc, 0), 1))))
+ {
+ mloc = cselib_subst_to_values (XEXP (mloc, 0),
+ GET_MODE (mloc));
+ moa.type = MO_VAL_USE;
+ moa.insn = cui->insn;
+ moa.u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ log_op_type (moa.u.loc, cui->bb, cui->insn,
+ moa.type, dump_file);
+ VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
+ &moa);
+ }
}
}
@@ -5122,7 +5139,7 @@ add_uses (rtx *ploc, void *data)
&& (GET_CODE (vloc) != CONST
|| for_each_rtx (&vloc, non_suitable_const, NULL)))
/* For constants don't look up any value. */;
- else if (!VAR_LOC_UNKNOWN_P (vloc)
+ else if (!VAR_LOC_UNKNOWN_P (vloc) && !unsuitable_loc (vloc)
&& (val = find_use_val (vloc, GET_MODE (oloc), cui)))
{
enum machine_mode mode2;
@@ -5168,32 +5185,36 @@ add_uses (rtx *ploc, void *data)
if (MEM_P (oloc)
&& !REG_P (XEXP (oloc, 0))
- && !MEM_P (XEXP (oloc, 0))
- && GET_CODE (XEXP (oloc, 0)) != ENTRY_VALUE
- && (GET_CODE (XEXP (oloc, 0)) != PLUS
- || XEXP (XEXP (oloc, 0), 0) != cfa_base_rtx
- || !CONST_INT_P (XEXP (XEXP (oloc, 0), 1))))
+ && !MEM_P (XEXP (oloc, 0)))
{
rtx mloc = oloc;
enum machine_mode address_mode = get_address_mode (mloc);
cselib_val *val
= cselib_lookup (XEXP (mloc, 0), address_mode, 0,
- GET_MODE (mloc));
+ GET_MODE (mloc));
if (val && !cselib_preserved_value_p (val))
{
micro_operation moa;
preserve_value (val);
- mloc = cselib_subst_to_values (XEXP (mloc, 0),
- GET_MODE (mloc));
- moa.type = MO_VAL_USE;
- moa.insn = cui->insn;
- moa.u.loc = gen_rtx_CONCAT (address_mode,
- val->val_rtx, mloc);
- if (dump_file && (dump_flags & TDF_DETAILS))
- log_op_type (moa.u.loc, cui->bb, cui->insn,
- moa.type, dump_file);
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
+
+ if (GET_CODE (XEXP (mloc, 0)) != ENTRY_VALUE
+ && (GET_CODE (XEXP (mloc, 0)) != PLUS
+ || XEXP (XEXP (mloc, 0), 0) != cfa_base_rtx
+ || !CONST_INT_P (XEXP (XEXP (mloc, 0), 1))))
+ {
+ mloc = cselib_subst_to_values (XEXP (mloc, 0),
+ GET_MODE (mloc));
+ moa.type = MO_VAL_USE;
+ moa.insn = cui->insn;
+ moa.u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ log_op_type (moa.u.loc, cui->bb, cui->insn,
+ moa.type, dump_file);
+ VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
+ &moa);
+ }
}
}
@@ -5255,7 +5276,18 @@ add_uses_1 (rtx *x, void *cui)
for_each_rtx (x, add_uses, cui);
}
-#define EXPR_DEPTH (PARAM_VALUE (PARAM_MAX_VARTRACK_EXPR_DEPTH))
+/* This is the value used during expansion of locations. We want it
+ to be unbounded, so that variables expanded deep in a recursion
+ nest are fully evaluated, so that their values are cached
+ correctly. We avoid recursion cycles through other means, and we
+ don't unshare RTL, so excess complexity is not a problem. */
+#define EXPR_DEPTH (INT_MAX)
+/* We use this to keep too-complex expressions from being emitted as
+ location notes, and then to debug information. Users can trade
+ compile time for ridiculously complex expressions, although they're
+ seldom useful, and they may often have to be discarded as not
+ representable anyway. */
+#define EXPR_USE_DEPTH (PARAM_VALUE (PARAM_MAX_VARTRACK_EXPR_DEPTH))
/* Attempt to reverse the EXPR operation in the debug info. Say for
reg1 = reg2 + 6 even when reg2 is no longer live we
@@ -5382,10 +5414,8 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
mo.u.loc = loc;
if (GET_CODE (expr) == SET
&& SET_DEST (expr) == loc
- && REGNO (loc) < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (argument_reg_set, REGNO (loc))
- && find_use_val (loc, mode, cui)
- && GET_CODE (SET_SRC (expr)) != ASM_OPERANDS)
+ && !unsuitable_loc (SET_SRC (expr))
+ && find_use_val (loc, mode, cui))
{
gcc_checking_assert (type == MO_VAL_SET);
mo.u.loc = gen_rtx_SET (VOIDmode, loc, SET_SRC (expr));
@@ -5422,11 +5452,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
{
if (MEM_P (loc) && type == MO_VAL_SET
&& !REG_P (XEXP (loc, 0))
- && !MEM_P (XEXP (loc, 0))
- && GET_CODE (XEXP (loc, 0)) != ENTRY_VALUE
- && (GET_CODE (XEXP (loc, 0)) != PLUS
- || XEXP (XEXP (loc, 0), 0) != cfa_base_rtx
- || !CONST_INT_P (XEXP (XEXP (loc, 0), 1))))
+ && !MEM_P (XEXP (loc, 0)))
{
rtx mloc = loc;
enum machine_mode address_mode = get_address_mode (mloc);
@@ -5437,15 +5463,23 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
if (val && !cselib_preserved_value_p (val))
{
preserve_value (val);
- mo.type = MO_VAL_USE;
- mloc = cselib_subst_to_values (XEXP (mloc, 0),
- GET_MODE (mloc));
- mo.u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
- mo.insn = cui->insn;
- if (dump_file && (dump_flags & TDF_DETAILS))
- log_op_type (mo.u.loc, cui->bb, cui->insn,
- mo.type, dump_file);
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
+
+ if (GET_CODE (XEXP (mloc, 0)) != ENTRY_VALUE
+ && (GET_CODE (XEXP (mloc, 0)) != PLUS
+ || XEXP (XEXP (mloc, 0), 0) != cfa_base_rtx
+ || !CONST_INT_P (XEXP (XEXP (mloc, 0), 1))))
+ {
+ mloc = cselib_subst_to_values (XEXP (mloc, 0),
+ GET_MODE (mloc));
+ mo.type = MO_VAL_USE;
+ mo.insn = cui->insn;
+ mo.u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ log_op_type (mo.u.loc, cui->bb, cui->insn,
+ mo.type, dump_file);
+ VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
+ }
}
}
@@ -5893,7 +5927,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
tree dtemp = VEC_index (tree, *debug_args, ix + 1);
enum machine_mode mode = DECL_MODE (dtemp);
item = gen_rtx_DEBUG_PARAMETER_REF (mode, param);
- item = gen_rtx_CONCAT (mode, item, DECL_RTL (dtemp));
+ item = gen_rtx_CONCAT (mode, item, DECL_RTL_KNOWN_SET (dtemp));
call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
call_arguments);
}
@@ -6705,7 +6739,7 @@ dump_var (variable var)
for (i = 0; i < var->n_var_parts; i++)
{
fprintf (dump_file, " offset %ld\n",
- (long) var->var_part[i].offset);
+ (long)(var->onepart ? 0 : VAR_PART_OFFSET (var, i)));
for (node = var->var_part[i].loc_chain; node; node = node->next)
{
fprintf (dump_file, " ");
@@ -6766,6 +6800,73 @@ dump_dataflow_sets (void)
}
}
+/* Return the variable for DV in dropped_values, inserting one if
+ requested with INSERT. */
+
+static inline variable
+variable_from_dropped (decl_or_value dv, enum insert_option insert)
+{
+ void **slot;
+ variable empty_var;
+ onepart_enum_t onepart;
+
+ slot = htab_find_slot_with_hash (dropped_values, dv, dv_htab_hash (dv),
+ insert);
+
+ if (!slot)
+ return NULL;
+
+ if (*slot)
+ return (variable) *slot;
+
+ gcc_checking_assert (insert == INSERT);
+
+ onepart = dv_onepart_p (dv);
+
+ gcc_checking_assert (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR);
+
+ empty_var = (variable) pool_alloc (onepart_pool (onepart));
+ empty_var->dv = dv;
+ empty_var->refcount = 1;
+ empty_var->n_var_parts = 0;
+ empty_var->onepart = onepart;
+ empty_var->in_changed_variables = false;
+ empty_var->var_part[0].loc_chain = NULL;
+ empty_var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (empty_var) = NULL;
+ set_dv_changed (dv, true);
+
+ *slot = empty_var;
+
+ return empty_var;
+}
+
+/* Recover the one-part aux from dropped_values. */
+
+static struct onepart_aux *
+recover_dropped_1paux (variable var)
+{
+ variable dvar;
+
+ gcc_checking_assert (var->onepart);
+
+ if (VAR_LOC_1PAUX (var))
+ return VAR_LOC_1PAUX (var);
+
+ if (var->onepart == ONEPART_VDECL)
+ return NULL;
+
+ dvar = variable_from_dropped (var->dv, NO_INSERT);
+
+ if (!dvar)
+ return NULL;
+
+ VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (dvar);
+ VAR_LOC_1PAUX (dvar) = NULL;
+
+ return VAR_LOC_1PAUX (var);
+}
+
/* Add variable VAR to the hash table of changed variables and
if it has no locations delete it from SET's hash table. */
@@ -6777,7 +6878,6 @@ variable_was_changed (variable var, dataflow_set *set)
if (emit_notes)
{
void **slot;
- bool old_cur_loc_changed = false;
/* Remember this decl or VALUE has been added to changed_variables. */
set_dv_changed (var->dv, true);
@@ -6791,30 +6891,76 @@ variable_was_changed (variable var, dataflow_set *set)
variable old_var = (variable) *slot;
gcc_assert (old_var->in_changed_variables);
old_var->in_changed_variables = false;
- old_cur_loc_changed = old_var->cur_loc_changed;
+ if (var != old_var && var->onepart)
+ {
+ /* Restore the auxiliary info from an empty variable
+ previously created for changed_variables, so it is
+ not lost. */
+ gcc_checking_assert (!VAR_LOC_1PAUX (var));
+ VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (old_var);
+ VAR_LOC_1PAUX (old_var) = NULL;
+ }
variable_htab_free (*slot);
}
+
if (set && var->n_var_parts == 0)
{
- variable empty_var;
+ onepart_enum_t onepart = var->onepart;
+ variable empty_var = NULL;
+ void **dslot = NULL;
- empty_var = (variable) pool_alloc (dv_pool (var->dv));
- empty_var->dv = var->dv;
- empty_var->refcount = 1;
- empty_var->n_var_parts = 0;
- empty_var->cur_loc_changed = true;
+ if (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR)
+ {
+ dslot = htab_find_slot_with_hash (dropped_values, var->dv,
+ dv_htab_hash (var->dv),
+ INSERT);
+ empty_var = (variable) *dslot;
+
+ if (empty_var)
+ {
+ gcc_checking_assert (!empty_var->in_changed_variables);
+ if (!VAR_LOC_1PAUX (var))
+ {
+ VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (empty_var);
+ VAR_LOC_1PAUX (empty_var) = NULL;
+ }
+ else
+ gcc_checking_assert (!VAR_LOC_1PAUX (empty_var));
+ }
+ }
+
+ if (!empty_var)
+ {
+ empty_var = (variable) pool_alloc (onepart_pool (onepart));
+ empty_var->dv = var->dv;
+ empty_var->refcount = 1;
+ empty_var->n_var_parts = 0;
+ empty_var->onepart = onepart;
+ if (dslot)
+ {
+ empty_var->refcount++;
+ *dslot = empty_var;
+ }
+ }
+ else
+ empty_var->refcount++;
empty_var->in_changed_variables = true;
*slot = empty_var;
+ if (onepart)
+ {
+ empty_var->var_part[0].loc_chain = NULL;
+ empty_var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (empty_var) = VAR_LOC_1PAUX (var);
+ VAR_LOC_1PAUX (var) = NULL;
+ }
goto drop_var;
}
else
{
+ if (var->onepart && !VAR_LOC_1PAUX (var))
+ recover_dropped_1paux (var);
var->refcount++;
var->in_changed_variables = true;
- /* If within processing one uop a variable is deleted
- and then readded, we need to assume it has changed. */
- if (old_cur_loc_changed)
- var->cur_loc_changed = true;
*slot = var;
}
}
@@ -6849,13 +6995,24 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
{
int pos, low, high;
+ if (var->onepart)
+ {
+ if (offset != 0)
+ return -1;
+
+ if (insertion_point)
+ *insertion_point = 0;
+
+ return var->n_var_parts - 1;
+ }
+
/* Find the location part. */
low = 0;
high = var->n_var_parts;
while (low != high)
{
pos = (low + high) / 2;
- if (var->var_part[pos].offset < offset)
+ if (VAR_PART_OFFSET (var, pos) < offset)
low = pos + 1;
else
high = pos;
@@ -6865,7 +7022,7 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
if (insertion_point)
*insertion_point = pos;
- if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
+ if (pos < var->n_var_parts && VAR_PART_OFFSET (var, pos) == offset)
return pos;
return -1;
@@ -6880,26 +7037,34 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
location_chain node, next;
location_chain *nextp;
variable var;
- bool onepart = dv_onepart_p (dv);
-
- gcc_assert (offset == 0 || !onepart);
- gcc_assert (loc != dv_as_opaque (dv));
+ onepart_enum_t onepart;
var = (variable) *slot;
+ if (var)
+ onepart = var->onepart;
+ else
+ onepart = dv_onepart_p (dv);
+
+ gcc_checking_assert (offset == 0 || !onepart);
+ gcc_checking_assert (loc != dv_as_opaque (dv));
+
if (! flag_var_tracking_uninit)
initialized = VAR_INIT_STATUS_INITIALIZED;
if (!var)
{
/* Create new variable information. */
- var = (variable) pool_alloc (dv_pool (dv));
+ var = (variable) pool_alloc (onepart_pool (onepart));
var->dv = dv;
var->refcount = 1;
var->n_var_parts = 1;
- var->cur_loc_changed = false;
+ var->onepart = onepart;
var->in_changed_variables = false;
- var->var_part[0].offset = offset;
+ if (var->onepart)
+ VAR_LOC_1PAUX (var) = NULL;
+ else
+ VAR_PART_OFFSET (var, 0) = offset;
var->var_part[0].loc_chain = NULL;
var->var_part[0].cur_loc = NULL;
*slot = var;
@@ -7054,7 +7219,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
thus there are at most MAX_VAR_PARTS different offsets. */
gcc_assert (var->n_var_parts < MAX_VAR_PARTS
- && (!var->n_var_parts || !dv_onepart_p (var->dv)));
+ && (!var->n_var_parts || !onepart));
/* We have to move the elements of array starting at index
inspos to the next position. */
@@ -7062,7 +7227,8 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
var->var_part[pos] = var->var_part[pos - 1];
var->n_var_parts++;
- var->var_part[pos].offset = offset;
+ gcc_checking_assert (!onepart);
+ VAR_PART_OFFSET (var, pos) = offset;
var->var_part[pos].loc_chain = NULL;
var->var_part[pos].cur_loc = NULL;
}
@@ -7083,10 +7249,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
if (node->set_src != NULL && set_src == NULL)
set_src = node->set_src;
if (var->var_part[pos].cur_loc == node->loc)
- {
- var->var_part[pos].cur_loc = NULL;
- var->cur_loc_changed = true;
- }
+ var->var_part[pos].cur_loc = NULL;
pool_free (loc_chain_pool, node);
*nextp = next;
break;
@@ -7106,9 +7269,6 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
node->next = *nextp;
*nextp = node;
- if (onepart && emit_notes)
- add_value_chains (var->dv, loc);
-
/* If no location was emitted do so. */
if (var->var_part[pos].cur_loc == NULL)
variable_was_changed (var, set);
@@ -7238,6 +7398,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
location_chain node, next;
location_chain *nextp;
bool changed;
+ rtx cur_loc;
if (shared_var_p (var, set->vars))
{
@@ -7258,6 +7419,11 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
}
}
+ if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
+ cur_loc = VAR_LOC_FROM (var);
+ else
+ cur_loc = var->var_part[pos].cur_loc;
+
/* Delete the location part. */
changed = false;
nextp = &var->var_part[pos].loc_chain;
@@ -7268,16 +7434,15 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
&& REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, loc))
{
- if (emit_notes && pos == 0 && dv_onepart_p (var->dv))
- remove_value_chains (var->dv, node->loc);
/* If we have deleted the location which was last emitted
we have to emit new location so add the variable to set
of changed variables. */
- if (var->var_part[pos].cur_loc == node->loc)
+ if (cur_loc == node->loc)
{
changed = true;
var->var_part[pos].cur_loc = NULL;
- var->cur_loc_changed = true;
+ if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
+ VAR_LOC_FROM (var) = NULL;
}
pool_free (loc_chain_pool, node);
*nextp = next;
@@ -7291,8 +7456,6 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
{
changed = true;
var->n_var_parts--;
- if (emit_notes)
- var->cur_loc_changed = true;
while (pos < var->n_var_parts)
{
var->var_part[pos] = var->var_part[pos + 1];
@@ -7321,6 +7484,12 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
delete_slot_part (set, loc, slot, offset);
}
+DEF_VEC_P (variable);
+DEF_VEC_ALLOC_P (variable, heap);
+
+DEF_VEC_ALLOC_P_STACK (rtx);
+#define VEC_rtx_stack_alloc(alloc) VEC_stack_alloc (rtx, alloc)
+
/* Structure for passing some other parameters to function
vt_expand_loc_callback. */
struct expand_loc_callback_data
@@ -7328,56 +7497,368 @@ struct expand_loc_callback_data
/* The variables and values active at this point. */
htab_t vars;
- /* True in vt_expand_loc_dummy calls, no rtl should be allocated.
- Non-NULL should be returned if vt_expand_loc would return
- non-NULL in that case, NULL otherwise. cur_loc_changed should be
- computed and cur_loc recomputed when possible (but just once
- per emit_notes_for_changes call). */
- bool dummy;
-
- /* True if expansion of subexpressions had to recompute some
- VALUE/DEBUG_EXPR_DECL's cur_loc or used a VALUE/DEBUG_EXPR_DECL
- whose cur_loc has been already recomputed during current
- emit_notes_for_changes call. */
- bool cur_loc_changed;
-
- /* True if cur_loc should be ignored and any possible location
- returned. */
- bool ignore_cur_loc;
+ /* Stack of values and debug_exprs under expansion, and their
+ children. */
+ VEC (rtx, stack) *expanding;
+
+ /* Stack of values and debug_exprs whose expansion hit recursion
+ cycles. They will have VALUE_RECURSED_INTO marked when added to
+ this list. This flag will be cleared if any of its dependencies
+ resolves to a valid location. So, if the flag remains set at the
+ end of the search, we know no valid location for this one can
+ possibly exist. */
+ VEC (rtx, stack) *pending;
+
+ /* The maximum depth among the sub-expressions under expansion.
+ Zero indicates no expansion so far. */
+ int depth;
};
+/* Allocate the one-part auxiliary data structure for VAR, with enough
+ room for COUNT dependencies. */
+
+static void
+loc_exp_dep_alloc (variable var, int count)
+{
+ size_t allocsize;
+
+ gcc_checking_assert (var->onepart);
+
+ /* We can be called with COUNT == 0 to allocate the data structure
+ without any dependencies, e.g. for the backlinks only. However,
+ if we are specifying a COUNT, then the dependency list must have
+ been emptied before. It would be possible to adjust pointers or
+ force it empty here, but this is better done at an earlier point
+ in the algorithm, so we instead leave an assertion to catch
+ errors. */
+ gcc_checking_assert (!count
+ || VEC_empty (loc_exp_dep, VAR_LOC_DEP_VEC (var)));
+
+ if (VAR_LOC_1PAUX (var)
+ && VEC_space (loc_exp_dep, VAR_LOC_DEP_VEC (var), count))
+ return;
+
+ allocsize = offsetof (struct onepart_aux, deps)
+ + VEC_embedded_size (loc_exp_dep, count);
+
+ if (VAR_LOC_1PAUX (var))
+ {
+ VAR_LOC_1PAUX (var) = XRESIZEVAR (struct onepart_aux,
+ VAR_LOC_1PAUX (var), allocsize);
+ /* If the reallocation moves the onepaux structure, the
+ back-pointer to BACKLINKS in the first list member will still
+ point to its old location. Adjust it. */
+ if (VAR_LOC_DEP_LST (var))
+ VAR_LOC_DEP_LST (var)->pprev = VAR_LOC_DEP_LSTP (var);
+ }
+ else
+ {
+ VAR_LOC_1PAUX (var) = XNEWVAR (struct onepart_aux, allocsize);
+ *VAR_LOC_DEP_LSTP (var) = NULL;
+ VAR_LOC_FROM (var) = NULL;
+ VAR_LOC_DEPTH (var) = 0;
+ }
+ VEC_embedded_init (loc_exp_dep, VAR_LOC_DEP_VEC (var), count);
+}
+
+/* Remove all entries from the vector of active dependencies of VAR,
+ removing them from the back-links lists too. */
+
+static void
+loc_exp_dep_clear (variable var)
+{
+ while (!VEC_empty (loc_exp_dep, VAR_LOC_DEP_VEC (var)))
+ {
+ loc_exp_dep *led = VEC_last (loc_exp_dep, VAR_LOC_DEP_VEC (var));
+ if (led->next)
+ led->next->pprev = led->pprev;
+ if (led->pprev)
+ *led->pprev = led->next;
+ VEC_pop (loc_exp_dep, VAR_LOC_DEP_VEC (var));
+ }
+}
+
+/* Insert an active dependency from VAR on X to the vector of
+ dependencies, and add the corresponding back-link to X's list of
+ back-links in VARS. */
+
+static void
+loc_exp_insert_dep (variable var, rtx x, htab_t vars)
+{
+ decl_or_value dv;
+ variable xvar;
+ loc_exp_dep *led;
+
+ dv = dv_from_rtx (x);
+
+ /* ??? Build a vector of variables parallel to EXPANDING, to avoid
+ an additional look up? */
+ xvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+
+ if (!xvar)
+ {
+ xvar = variable_from_dropped (dv, NO_INSERT);
+ gcc_checking_assert (xvar);
+ }
+
+ /* No point in adding the same backlink more than once. This may
+ arise if say the same value appears in two complex expressions in
+ the same loc_list, or even more than once in a single
+ expression. */
+ if (VAR_LOC_DEP_LST (xvar) && VAR_LOC_DEP_LST (xvar)->dv == var->dv)
+ return;
+
+ VEC_quick_push (loc_exp_dep, VAR_LOC_DEP_VEC (var), NULL);
+ led = VEC_last (loc_exp_dep, VAR_LOC_DEP_VEC (var));
+ led->dv = var->dv;
+ led->value = x;
+
+ loc_exp_dep_alloc (xvar, 0);
+ led->pprev = VAR_LOC_DEP_LSTP (xvar);
+ led->next = *led->pprev;
+ if (led->next)
+ led->next->pprev = &led->next;
+ *led->pprev = led;
+}
+
+/* Create active dependencies of VAR on COUNT values starting at
+ VALUE, and corresponding back-links to the entries in VARS. Return
+ true if we found any pending-recursion results. */
+
+static bool
+loc_exp_dep_set (variable var, rtx result, rtx *value, int count, htab_t vars)
+{
+ bool pending_recursion = false;
+
+ gcc_checking_assert (VEC_empty (loc_exp_dep, VAR_LOC_DEP_VEC (var)));
+
+ /* Set up all dependencies from last_child (as set up at the end of
+ the loop above) to the end. */
+ loc_exp_dep_alloc (var, count);
+
+ while (count--)
+ {
+ rtx x = *value++;
+
+ if (!pending_recursion)
+ pending_recursion = !result && VALUE_RECURSED_INTO (x);
+
+ loc_exp_insert_dep (var, x, vars);
+ }
+
+ return pending_recursion;
+}
+
+/* Notify the back-links of IVAR that are pending recursion that we
+ have found a non-NIL value for it, so they are cleared for another
+ attempt to compute a current location. */
+
+static void
+notify_dependents_of_resolved_value (variable ivar, htab_t vars)
+{
+ loc_exp_dep *led, *next;
+
+ for (led = VAR_LOC_DEP_LST (ivar); led; led = next)
+ {
+ decl_or_value dv = led->dv;
+ variable var;
+
+ next = led->next;
+
+ if (dv_is_value_p (dv))
+ {
+ rtx value = dv_as_value (dv);
+
+ /* If we have already resolved it, leave it alone. */
+ if (!VALUE_RECURSED_INTO (value))
+ continue;
+
+ /* Check that VALUE_RECURSED_INTO, true from the test above,
+ implies NO_LOC_P. */
+ gcc_checking_assert (NO_LOC_P (value));
+
+ /* We won't notify variables that are being expanded,
+ because their dependency list is cleared before
+ recursing. */
+ VALUE_RECURSED_INTO (value) = false;
+
+ gcc_checking_assert (dv_changed_p (dv));
+ }
+ else if (!dv_changed_p (dv))
+ continue;
+
+ var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+
+ if (!var)
+ var = variable_from_dropped (dv, NO_INSERT);
+
+ if (var)
+ notify_dependents_of_resolved_value (var, vars);
+
+ if (next)
+ next->pprev = led->pprev;
+ if (led->pprev)
+ *led->pprev = next;
+ led->next = NULL;
+ led->pprev = NULL;
+ }
+}
+
+static rtx vt_expand_loc_callback (rtx x, bitmap regs,
+ int max_depth, void *data);
+
+/* Return the combined depth, when one sub-expression evaluated to
+ BEST_DEPTH and the previous known depth was SAVED_DEPTH. */
+
+static inline int
+update_depth (int saved_depth, int best_depth)
+{
+ /* If we didn't find anything, stick with what we had. */
+ if (!best_depth)
+ return saved_depth;
+
+ /* If we found hadn't found anything, use the depth of the current
+ expression. Do NOT add one extra level, we want to compute the
+ maximum depth among sub-expressions. We'll increment it later,
+ if appropriate. */
+ if (!saved_depth)
+ return best_depth;
+
+ if (saved_depth < best_depth)
+ return best_depth;
+ else
+ return saved_depth;
+}
+
+/* Expand VAR to a location RTX, updating its cur_loc. Use REGS and
+ DATA for cselib expand callback. If PENDRECP is given, indicate in
+ it whether any sub-expression couldn't be fully evaluated because
+ it is pending recursion resolution. */
+
+static inline rtx
+vt_expand_var_loc_chain (variable var, bitmap regs, void *data, bool *pendrecp)
+{
+ struct expand_loc_callback_data *elcd
+ = (struct expand_loc_callback_data *) data;
+ location_chain loc, next;
+ rtx result = NULL;
+ int first_child, result_first_child, last_child;
+ bool pending_recursion;
+ rtx loc_from = NULL;
+ struct elt_loc_list *cloc = NULL;
+ int depth, saved_depth = elcd->depth;
+
+ /* Clear all backlinks pointing at this, so that we're not notified
+ while we're active. */
+ loc_exp_dep_clear (var);
+
+ if (var->onepart == ONEPART_VALUE)
+ {
+ cselib_val *val = CSELIB_VAL_PTR (dv_as_value (var->dv));
+
+ gcc_checking_assert (cselib_preserved_value_p (val));
+
+ cloc = val->locs;
+ }
+
+ first_child = result_first_child = last_child
+ = VEC_length (rtx, elcd->expanding);
+
+ /* Attempt to expand each available location in turn. */
+ for (next = loc = var->n_var_parts ? var->var_part[0].loc_chain : NULL;
+ loc || cloc; loc = next)
+ {
+ result_first_child = last_child;
+
+ if (!loc || (GET_CODE (loc->loc) == ENTRY_VALUE && cloc))
+ {
+ loc_from = cloc->loc;
+ next = loc;
+ cloc = cloc->next;
+ if (unsuitable_loc (loc_from))
+ continue;
+ }
+ else
+ {
+ loc_from = loc->loc;
+ next = loc->next;
+ }
+
+ gcc_checking_assert (!unsuitable_loc (loc_from));
+
+ elcd->depth = 0;
+ result = cselib_expand_value_rtx_cb (loc_from, regs, EXPR_DEPTH,
+ vt_expand_loc_callback, data);
+ last_child = VEC_length (rtx, elcd->expanding);
+
+ if (result)
+ {
+ depth = elcd->depth;
+
+ gcc_checking_assert (depth || result_first_child == last_child);
+
+ if (last_child - result_first_child != 1)
+ depth++;
+
+ if (depth <= EXPR_USE_DEPTH)
+ break;
+
+ result = NULL;
+ }
+
+ /* Set it up in case we leave the loop. */
+ depth = 0;
+ loc_from = NULL;
+ result_first_child = first_child;
+ }
+
+ /* Register all encountered dependencies as active. */
+ pending_recursion = loc_exp_dep_set
+ (var, result, VEC_address (rtx, elcd->expanding) + result_first_child,
+ last_child - result_first_child, elcd->vars);
+
+ VEC_truncate (rtx, elcd->expanding, first_child);
+
+ /* Record where the expansion came from. */
+ gcc_checking_assert (!result || !pending_recursion);
+ VAR_LOC_FROM (var) = loc_from;
+ VAR_LOC_DEPTH (var) = depth;
+
+ elcd->depth = update_depth (saved_depth, depth);
+
+ /* Indicate whether any of the dependencies are pending recursion
+ resolution. */
+ if (pendrecp)
+ *pendrecp = pending_recursion;
+
+ if (!pendrecp || !pending_recursion)
+ var->var_part[0].cur_loc = result;
+
+ return result;
+}
+
/* Callback for cselib_expand_value, that looks for expressions
holding the value in the var-tracking hash tables. Return X for
standard processing, anything else is to be used as-is. */
static rtx
-vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
+vt_expand_loc_callback (rtx x, bitmap regs,
+ int max_depth ATTRIBUTE_UNUSED,
+ void *data)
{
struct expand_loc_callback_data *elcd
= (struct expand_loc_callback_data *) data;
- bool dummy = elcd->dummy;
- bool cur_loc_changed = elcd->cur_loc_changed;
- rtx cur_loc;
decl_or_value dv;
variable var;
- location_chain loc;
- rtx result, subreg, xret;
+ rtx result, subreg;
+ bool pending_recursion = false;
+ bool from_empty = false;
switch (GET_CODE (x))
{
case SUBREG:
- if (dummy)
- {
- if (cselib_dummy_expand_value_rtx_cb (SUBREG_REG (x), regs,
- max_depth - 1,
- vt_expand_loc_callback, data))
- return pc_rtx;
- else
- return NULL;
- }
-
subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
- max_depth - 1,
+ EXPR_DEPTH,
vt_expand_loc_callback, data);
if (!subreg)
@@ -7395,148 +7876,172 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
return result;
case DEBUG_EXPR:
- dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
- xret = NULL;
- break;
-
case VALUE:
- dv = dv_from_value (x);
- xret = x;
+ dv = dv_from_rtx (x);
break;
default:
return x;
}
- if (VALUE_RECURSED_INTO (x))
+ VEC_safe_push (rtx, stack, elcd->expanding, x);
+
+ /* Check that VALUE_RECURSED_INTO implies NO_LOC_P. */
+ gcc_checking_assert (!VALUE_RECURSED_INTO (x) || NO_LOC_P (x));
+
+ if (NO_LOC_P (x))
return NULL;
var = (variable) htab_find_with_hash (elcd->vars, dv, dv_htab_hash (dv));
if (!var)
{
- if (dummy && dv_changed_p (dv))
- elcd->cur_loc_changed = true;
- return xret;
+ from_empty = true;
+ var = variable_from_dropped (dv, INSERT);
}
- if (var->n_var_parts == 0)
+ gcc_checking_assert (var);
+
+ if (!dv_changed_p (dv))
{
- if (dummy)
- elcd->cur_loc_changed = true;
- return xret;
- }
+ gcc_checking_assert (!NO_LOC_P (x));
+ gcc_checking_assert (var->var_part[0].cur_loc);
+ gcc_checking_assert (VAR_LOC_1PAUX (var));
+ gcc_checking_assert (VAR_LOC_1PAUX (var)->depth);
- gcc_assert (var->n_var_parts == 1);
+ elcd->depth = update_depth (elcd->depth, VAR_LOC_1PAUX (var)->depth);
+
+ return var->var_part[0].cur_loc;
+ }
VALUE_RECURSED_INTO (x) = true;
- result = NULL;
+ /* This is tentative, but it makes some tests simpler. */
+ NO_LOC_P (x) = true;
+
+ gcc_checking_assert (var->n_var_parts == 1 || from_empty);
+
+ result = vt_expand_var_loc_chain (var, regs, data, &pending_recursion);
- if (var->var_part[0].cur_loc && !elcd->ignore_cur_loc)
+ if (pending_recursion)
{
- if (dummy)
- {
- if (cselib_dummy_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
- max_depth,
- vt_expand_loc_callback, data))
- result = pc_rtx;
- }
- else
- result = cselib_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
- max_depth,
- vt_expand_loc_callback, data);
- if (result)
- set_dv_changed (dv, false);
- cur_loc = var->var_part[0].cur_loc;
+ gcc_checking_assert (!result);
+ VEC_safe_push (rtx, stack, elcd->pending, x);
}
else
- cur_loc = NULL_RTX;
- if (!result && (dv_changed_p (dv) || elcd->ignore_cur_loc))
- {
- if (!elcd->ignore_cur_loc)
- set_dv_changed (dv, false);
- for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
- if (loc->loc == cur_loc)
- continue;
- else if (dummy)
- {
- elcd->cur_loc_changed = cur_loc_changed;
- if (cselib_dummy_expand_value_rtx_cb (loc->loc, regs, max_depth,
- vt_expand_loc_callback,
- data))
- {
- result = pc_rtx;
- break;
- }
- }
- else
- {
- result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth,
- vt_expand_loc_callback, data);
- if (result)
- break;
- }
- if (dummy && (result || var->var_part[0].cur_loc))
- var->cur_loc_changed = true;
- if (!elcd->ignore_cur_loc)
- var->var_part[0].cur_loc = loc ? loc->loc : NULL_RTX;
- }
- if (dummy)
{
- if (var->cur_loc_changed)
- elcd->cur_loc_changed = true;
- else if (!result && var->var_part[0].cur_loc == NULL_RTX)
- elcd->cur_loc_changed = cur_loc_changed;
+ NO_LOC_P (x) = !result;
+ VALUE_RECURSED_INTO (x) = false;
+ set_dv_changed (dv, false);
+
+ if (result)
+ notify_dependents_of_resolved_value (var, elcd->vars);
}
- VALUE_RECURSED_INTO (x) = false;
- if (result)
- return result;
- else
- return xret;
+ return result;
}
-/* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
- tables. */
+/* While expanding variables, we may encounter recursion cycles
+ because of mutual (possibly indirect) dependencies between two
+ particular variables (or values), say A and B. If we're trying to
+ expand A when we get to B, which in turn attempts to expand A, if
+ we can't find any other expansion for B, we'll add B to this
+ pending-recursion stack, and tentatively return NULL for its
+ location. This tentative value will be used for any other
+ occurrences of B, unless A gets some other location, in which case
+ it will notify B that it is worth another try at computing a
+ location for it, and it will use the location computed for A then.
+ At the end of the expansion, the tentative NULL locations become
+ final for all members of PENDING that didn't get a notification.
+ This function performs this finalization of NULL locations. */
+
+static void
+resolve_expansions_pending_recursion (VEC (rtx, stack) *pending)
+{
+ while (!VEC_empty (rtx, pending))
+ {
+ rtx x = VEC_pop (rtx, pending);
+ decl_or_value dv;
+
+ if (!VALUE_RECURSED_INTO (x))
+ continue;
+
+ gcc_checking_assert (NO_LOC_P (x));
+ VALUE_RECURSED_INTO (x) = false;
+ dv = dv_from_rtx (x);
+ gcc_checking_assert (dv_changed_p (dv));
+ set_dv_changed (dv, false);
+ }
+}
+
+/* Initialize expand_loc_callback_data D with variable hash table V.
+ It must be a macro because of alloca (VEC stack). */
+#define INIT_ELCD(d, v) \
+ do \
+ { \
+ (d).vars = (v); \
+ (d).expanding = VEC_alloc (rtx, stack, 4); \
+ (d).pending = VEC_alloc (rtx, stack, 4); \
+ (d).depth = 0; \
+ } \
+ while (0)
+/* Finalize expand_loc_callback_data D, resolved to location L. */
+#define FINI_ELCD(d, l) \
+ do \
+ { \
+ resolve_expansions_pending_recursion ((d).pending); \
+ VEC_free (rtx, stack, (d).pending); \
+ VEC_free (rtx, stack, (d).expanding); \
+ \
+ if ((l) && MEM_P (l)) \
+ (l) = targetm.delegitimize_address (l); \
+ } \
+ while (0)
+
+/* Expand VALUEs and DEBUG_EXPRs in LOC to a location, using the
+ equivalences in VARS, updating their CUR_LOCs in the process. */
static rtx
-vt_expand_loc (rtx loc, htab_t vars, bool ignore_cur_loc)
+vt_expand_loc (rtx loc, htab_t vars)
{
struct expand_loc_callback_data data;
+ rtx result;
if (!MAY_HAVE_DEBUG_INSNS)
return loc;
- data.vars = vars;
- data.dummy = false;
- data.cur_loc_changed = false;
- data.ignore_cur_loc = ignore_cur_loc;
- loc = cselib_expand_value_rtx_cb (loc, scratch_regs, EXPR_DEPTH,
- vt_expand_loc_callback, &data);
+ INIT_ELCD (data, vars);
- if (loc && MEM_P (loc))
- loc = targetm.delegitimize_address (loc);
- return loc;
+ result = cselib_expand_value_rtx_cb (loc, scratch_regs, EXPR_DEPTH,
+ vt_expand_loc_callback, &data);
+
+ FINI_ELCD (data, result);
+
+ return result;
}
-/* Like vt_expand_loc, but only return true/false (whether vt_expand_loc
- would succeed or not, without actually allocating new rtxes. */
+/* Expand the one-part VARiable to a location, using the equivalences
+ in VARS, updating their CUR_LOCs in the process. */
-static bool
-vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
+static rtx
+vt_expand_1pvar (variable var, htab_t vars)
{
struct expand_loc_callback_data data;
- bool ret;
-
- gcc_assert (MAY_HAVE_DEBUG_INSNS);
- data.vars = vars;
- data.dummy = true;
- data.cur_loc_changed = false;
- data.ignore_cur_loc = false;
- ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, EXPR_DEPTH,
- vt_expand_loc_callback, &data);
- *pcur_loc_changed = data.cur_loc_changed;
- return ret;
+ rtx loc;
+
+ gcc_checking_assert (var->onepart && var->n_var_parts == 1);
+
+ if (!dv_changed_p (var->dv))
+ return var->var_part[0].cur_loc;
+
+ INIT_ELCD (data, vars);
+
+ loc = vt_expand_var_loc_chain (var, scratch_regs, &data, NULL);
+
+ gcc_checking_assert (VEC_empty (rtx, data.expanding));
+
+ FINI_ELCD (data, loc);
+
+ return loc;
}
/* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
@@ -7561,49 +8066,57 @@ emit_note_insn_var_location (void **varp, void *data)
tree decl;
location_chain lc;
- if (dv_is_value_p (var->dv))
- goto value_or_debug_decl;
+ gcc_checking_assert (var->onepart == NOT_ONEPART
+ || var->onepart == ONEPART_VDECL);
decl = dv_as_decl (var->dv);
- if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
- goto value_or_debug_decl;
-
complete = true;
last_limit = 0;
n_var_parts = 0;
- if (!MAY_HAVE_DEBUG_INSNS)
- {
- for (i = 0; i < var->n_var_parts; i++)
- if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain)
- {
- var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
- var->cur_loc_changed = true;
- }
- if (var->n_var_parts == 0)
- var->cur_loc_changed = true;
- }
- if (!var->cur_loc_changed)
- goto clear;
+ if (!var->onepart)
+ for (i = 0; i < var->n_var_parts; i++)
+ if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain)
+ var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
for (i = 0; i < var->n_var_parts; i++)
{
enum machine_mode mode, wider_mode;
rtx loc2;
+ HOST_WIDE_INT offset;
- if (last_limit < var->var_part[i].offset)
+ if (i == 0 && var->onepart)
{
- complete = false;
- break;
+ gcc_checking_assert (var->n_var_parts == 1);
+ offset = 0;
+ initialized = VAR_INIT_STATUS_INITIALIZED;
+ loc2 = vt_expand_1pvar (var, vars);
}
- else if (last_limit > var->var_part[i].offset)
- continue;
- offsets[n_var_parts] = var->var_part[i].offset;
- if (!var->var_part[i].cur_loc)
+ else
{
- complete = false;
- continue;
+ if (last_limit < VAR_PART_OFFSET (var, i))
+ {
+ complete = false;
+ break;
+ }
+ else if (last_limit > VAR_PART_OFFSET (var, i))
+ continue;
+ offset = VAR_PART_OFFSET (var, i);
+ if (!var->var_part[i].cur_loc)
+ {
+ complete = false;
+ continue;
+ }
+ for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
+ if (var->var_part[i].cur_loc == lc->loc)
+ {
+ initialized = lc->init;
+ break;
+ }
+ gcc_assert (lc);
+ loc2 = var->var_part[i].cur_loc;
}
- loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars, false);
+
+ offsets[n_var_parts] = offset;
if (!loc2)
{
complete = false;
@@ -7611,29 +8124,22 @@ emit_note_insn_var_location (void **varp, void *data)
}
loc[n_var_parts] = loc2;
mode = GET_MODE (var->var_part[i].cur_loc);
- if (mode == VOIDmode && dv_onepart_p (var->dv))
+ if (mode == VOIDmode && var->onepart)
mode = DECL_MODE (decl);
- for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
- if (var->var_part[i].cur_loc == lc->loc)
- {
- initialized = lc->init;
- break;
- }
- gcc_assert (lc);
last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
/* Attempt to merge adjacent registers or memory. */
wider_mode = GET_MODE_WIDER_MODE (mode);
for (j = i + 1; j < var->n_var_parts; j++)
- if (last_limit <= var->var_part[j].offset)
+ if (last_limit <= VAR_PART_OFFSET (var, j))
break;
if (j < var->n_var_parts
&& wider_mode != VOIDmode
&& var->var_part[j].cur_loc
&& mode == GET_MODE (var->var_part[j].cur_loc)
&& (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
- && last_limit == var->var_part[j].offset
- && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars, false))
+ && last_limit == (var->onepart ? 0 : VAR_PART_OFFSET (var, j))
+ && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars))
&& GET_CODE (loc[n_var_parts]) == GET_CODE (loc2))
{
rtx new_loc = NULL;
@@ -7746,152 +8252,152 @@ emit_note_insn_var_location (void **varp, void *data)
}
NOTE_VAR_LOCATION (note) = note_vl;
- clear:
set_dv_changed (var->dv, false);
- var->cur_loc_changed = false;
gcc_assert (var->in_changed_variables);
var->in_changed_variables = false;
htab_clear_slot (changed_variables, varp);
/* Continue traversing the hash table. */
return 1;
-
- value_or_debug_decl:
- if (dv_changed_p (var->dv) && var->n_var_parts)
- {
- location_chain lc;
- bool cur_loc_changed;
-
- if (var->var_part[0].cur_loc
- && vt_expand_loc_dummy (var->var_part[0].cur_loc, vars,
- &cur_loc_changed))
- goto clear;
- for (lc = var->var_part[0].loc_chain; lc; lc = lc->next)
- if (lc->loc != var->var_part[0].cur_loc
- && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
- break;
- var->var_part[0].cur_loc = lc ? lc->loc : NULL_RTX;
- }
- goto clear;
}
-DEF_VEC_P (variable);
-DEF_VEC_ALLOC_P (variable, heap);
-
-/* Stack of variable_def pointers that need processing with
- check_changed_vars_2. */
+/* While traversing changed_variables, push onto DATA (a stack of RTX
+ values) entries that aren't user variables. */
-static VEC (variable, heap) *changed_variables_stack;
-
-/* VALUEs with no variables that need set_dv_changed (val, false)
- called before check_changed_vars_3. */
+static int
+values_to_stack (void **slot, void *data)
+{
+ VEC (rtx, stack) **changed_values_stack = (VEC (rtx, stack) **)data;
+ variable var = (variable) *slot;
-static VEC (rtx, heap) *changed_values_stack;
+ if (var->onepart == ONEPART_VALUE)
+ VEC_safe_push (rtx, stack, *changed_values_stack, dv_as_value (var->dv));
+ else if (var->onepart == ONEPART_DEXPR)
+ VEC_safe_push (rtx, stack, *changed_values_stack,
+ DECL_RTL_KNOWN_SET (dv_as_decl (var->dv)));
-/* Helper function for check_changed_vars_1 and check_changed_vars_2. */
+ return 1;
+}
+/* Remove from changed_variables the entry whose DV corresponds to
+ value or debug_expr VAL. */
static void
-check_changed_vars_0 (decl_or_value dv, htab_t htab)
+remove_value_from_changed_variables (rtx val)
{
- value_chain vc
- = (value_chain) htab_find_with_hash (value_chains, dv, dv_htab_hash (dv));
+ decl_or_value dv = dv_from_rtx (val);
+ void **slot;
+ variable var;
- if (vc == NULL)
- return;
- for (vc = vc->next; vc; vc = vc->next)
- if (!dv_changed_p (vc->dv))
- {
- variable vcvar
- = (variable) htab_find_with_hash (htab, vc->dv,
- dv_htab_hash (vc->dv));
- if (vcvar)
- {
- set_dv_changed (vc->dv, true);
- VEC_safe_push (variable, heap, changed_variables_stack, vcvar);
- }
- else if (dv_is_value_p (vc->dv))
- {
- set_dv_changed (vc->dv, true);
- VEC_safe_push (rtx, heap, changed_values_stack,
- dv_as_value (vc->dv));
- check_changed_vars_0 (vc->dv, htab);
- }
- }
+ slot = htab_find_slot_with_hash (changed_variables,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ var = (variable) *slot;
+ var->in_changed_variables = false;
+ htab_clear_slot (changed_variables, slot);
}
-/* Populate changed_variables_stack with variable_def pointers
- that need variable_was_changed called on them. */
+/* If VAL (a value or debug_expr) has backlinks to variables actively
+ dependent on it in HTAB or in CHANGED_VARIABLES, mark them as
+ changed, adding to CHANGED_VALUES_STACK any dependencies that may
+ have dependencies of their own to notify. */
-static int
-check_changed_vars_1 (void **slot, void *data)
+static void
+notify_dependents_of_changed_value (rtx val, htab_t htab,
+ VEC (rtx, stack) **changed_values_stack)
{
- variable var = (variable) *slot;
- htab_t htab = (htab_t) data;
+ void **slot;
+ variable var;
+ loc_exp_dep *led;
+ decl_or_value dv = dv_from_rtx (val);
- if (dv_is_value_p (var->dv)
- || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
- check_changed_vars_0 (var->dv, htab);
- return 1;
-}
+ slot = htab_find_slot_with_hash (changed_variables,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ if (!slot)
+ slot = htab_find_slot_with_hash (htab,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ if (!slot)
+ slot = htab_find_slot_with_hash (dropped_values,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ var = (variable) *slot;
-/* Add VAR to changed_variables and also for VALUEs add recursively
- all DVs that aren't in changed_variables yet but reference the
- VALUE from its loc_chain. */
+ while ((led = VAR_LOC_DEP_LST (var)))
+ {
+ decl_or_value ldv = led->dv;
+ void **islot;
+ variable ivar;
-static void
-check_changed_vars_2 (variable var, htab_t htab)
-{
- variable_was_changed (var, NULL);
- if (dv_is_value_p (var->dv)
- || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
- check_changed_vars_0 (var->dv, htab);
+ /* Deactivate and remove the backlink, as it was “used upâ€. It
+ makes no sense to attempt to notify the same entity again:
+ either it will be recomputed and re-register an active
+ dependency, or it will still have the changed mark. */
+ if (led->next)
+ led->next->pprev = led->pprev;
+ if (led->pprev)
+ *led->pprev = led->next;
+ led->next = NULL;
+ led->pprev = NULL;
+
+ if (dv_changed_p (ldv))
+ continue;
+
+ switch (dv_onepart_p (ldv))
+ {
+ case ONEPART_VALUE:
+ case ONEPART_DEXPR:
+ set_dv_changed (ldv, true);
+ VEC_safe_push (rtx, stack, *changed_values_stack, dv_as_rtx (ldv));
+ break;
+
+ default:
+ islot = htab_find_slot_with_hash (htab, ldv, dv_htab_hash (ldv),
+ NO_INSERT);
+ ivar = (variable) *islot;
+ gcc_checking_assert (!VAR_LOC_DEP_LST (ivar));
+ variable_was_changed (ivar, NULL);
+ break;
+ }
+ }
}
-/* For each changed decl (except DEBUG_EXPR_DECLs) recompute
- cur_loc if needed (and cur_loc of all VALUEs and DEBUG_EXPR_DECLs
- it needs and are also in changed variables) and track whether
- cur_loc (or anything it uses to compute location) had to change
- during the current emit_notes_for_changes call. */
+/* Take out of changed_variables any entries that don't refer to use
+ variables. Back-propagate change notifications from values and
+ debug_exprs to their active dependencies in HTAB or in
+ CHANGED_VARIABLES. */
-static int
-check_changed_vars_3 (void **slot, void *data)
+static void
+process_changed_values (htab_t htab)
{
- variable var = (variable) *slot;
- htab_t vars = (htab_t) data;
- int i;
- location_chain lc;
- bool cur_loc_changed;
+ int i, n;
+ rtx val;
+ VEC (rtx, stack) *changed_values_stack = VEC_alloc (rtx, stack, 20);
- if (dv_is_value_p (var->dv)
- || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
- return 1;
+ /* Move values from changed_variables to changed_values_stack. */
+ htab_traverse (changed_variables, values_to_stack, &changed_values_stack);
- for (i = 0; i < var->n_var_parts; i++)
+ /* Back-propagate change notifications in values while popping
+ them from the stack. */
+ for (n = i = VEC_length (rtx, changed_values_stack);
+ i > 0; i = VEC_length (rtx, changed_values_stack))
{
- if (var->var_part[i].cur_loc
- && vt_expand_loc_dummy (var->var_part[i].cur_loc, vars,
- &cur_loc_changed))
+ val = VEC_pop (rtx, changed_values_stack);
+ notify_dependents_of_changed_value (val, htab, &changed_values_stack);
+
+ /* This condition will hold when visiting each of the entries
+ originally in changed_variables. We can't remove them
+ earlier because this could drop the backlinks before we got a
+ chance to use them. */
+ if (i == n)
{
- if (cur_loc_changed)
- var->cur_loc_changed = true;
- continue;
+ remove_value_from_changed_variables (val);
+ n--;
}
- for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
- if (lc->loc != var->var_part[i].cur_loc
- && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
- break;
- if (lc || var->var_part[i].cur_loc)
- var->cur_loc_changed = true;
- var->var_part[i].cur_loc = lc ? lc->loc : NULL_RTX;
}
- if (var->n_var_parts == 0)
- var->cur_loc_changed = true;
- return 1;
+
+ VEC_free (rtx, stack, changed_values_stack);
}
/* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
- CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
- shall be emitted before of after instruction INSN. */
+ CHANGED_VARIABLES and delete this chain. WHERE specifies whether
+ the notes shall be emitted before of after instruction INSN. */
static void
emit_notes_for_changes (rtx insn, enum emit_note_where where,
@@ -7904,19 +8410,7 @@ emit_notes_for_changes (rtx insn, enum emit_note_where where,
return;
if (MAY_HAVE_DEBUG_INSNS)
- {
- /* Unfortunately this has to be done in two steps, because
- we can't traverse a hashtab into which we are inserting
- through variable_was_changed. */
- htab_traverse (changed_variables, check_changed_vars_1, htab);
- while (VEC_length (variable, changed_variables_stack) > 0)
- check_changed_vars_2 (VEC_pop (variable, changed_variables_stack),
- htab);
- while (VEC_length (rtx, changed_values_stack) > 0)
- set_dv_changed (dv_from_value (VEC_pop (rtx, changed_values_stack)),
- false);
- htab_traverse (changed_variables, check_changed_vars_3, htab);
- }
+ process_changed_values (htab);
data.insn = insn;
data.where = where;
@@ -7941,78 +8435,59 @@ emit_notes_for_differences_1 (void **slot, void *data)
if (!new_var)
{
/* Variable has disappeared. */
- variable empty_var;
-
- empty_var = (variable) pool_alloc (dv_pool (old_var->dv));
- empty_var->dv = old_var->dv;
- empty_var->refcount = 0;
- empty_var->n_var_parts = 0;
- empty_var->cur_loc_changed = false;
- empty_var->in_changed_variables = false;
- if (dv_onepart_p (old_var->dv))
- {
- location_chain lc;
+ variable empty_var = NULL;
- gcc_assert (old_var->n_var_parts == 1);
- for (lc = old_var->var_part[0].loc_chain; lc; lc = lc->next)
- remove_value_chains (old_var->dv, lc->loc);
- }
- variable_was_changed (empty_var, NULL);
- /* Continue traversing the hash table. */
- return 1;
- }
- if (variable_different_p (old_var, new_var))
- {
- if (dv_onepart_p (old_var->dv))
+ if (old_var->onepart == ONEPART_VALUE
+ || old_var->onepart == ONEPART_DEXPR)
{
- location_chain lc1, lc2;
-
- gcc_assert (old_var->n_var_parts == 1
- && new_var->n_var_parts == 1);
- lc1 = old_var->var_part[0].loc_chain;
- lc2 = new_var->var_part[0].loc_chain;
- while (lc1
- && lc2
- && ((REG_P (lc1->loc) && REG_P (lc2->loc))
- || rtx_equal_p (lc1->loc, lc2->loc)))
+ empty_var = variable_from_dropped (old_var->dv, NO_INSERT);
+ if (empty_var)
{
- lc1 = lc1->next;
- lc2 = lc2->next;
+ gcc_checking_assert (!empty_var->in_changed_variables);
+ if (!VAR_LOC_1PAUX (old_var))
+ {
+ VAR_LOC_1PAUX (old_var) = VAR_LOC_1PAUX (empty_var);
+ VAR_LOC_1PAUX (empty_var) = NULL;
+ }
+ else
+ gcc_checking_assert (!VAR_LOC_1PAUX (empty_var));
}
- for (; lc2; lc2 = lc2->next)
- add_value_chains (old_var->dv, lc2->loc);
- for (; lc1; lc1 = lc1->next)
- remove_value_chains (old_var->dv, lc1->loc);
}
- variable_was_changed (new_var, NULL);
- }
- /* Update cur_loc. */
- if (old_var != new_var)
- {
- int i;
- for (i = 0; i < new_var->n_var_parts; i++)
+
+ if (!empty_var)
{
- new_var->var_part[i].cur_loc = NULL;
- if (old_var->n_var_parts != new_var->n_var_parts
- || old_var->var_part[i].offset != new_var->var_part[i].offset)
- new_var->cur_loc_changed = true;
- else if (old_var->var_part[i].cur_loc != NULL)
- {
- location_chain lc;
- rtx cur_loc = old_var->var_part[i].cur_loc;
+ empty_var = (variable) pool_alloc (onepart_pool (old_var->onepart));
+ empty_var->dv = old_var->dv;
+ empty_var->refcount = 0;
+ empty_var->n_var_parts = 0;
+ empty_var->onepart = old_var->onepart;
+ empty_var->in_changed_variables = false;
+ }
- for (lc = new_var->var_part[i].loc_chain; lc; lc = lc->next)
- if (lc->loc == cur_loc
- || rtx_equal_p (cur_loc, lc->loc))
- {
- new_var->var_part[i].cur_loc = lc->loc;
- break;
- }
- if (lc == NULL)
- new_var->cur_loc_changed = true;
- }
+ if (empty_var->onepart)
+ {
+ /* Propagate the auxiliary data to (ultimately)
+ changed_variables. */
+ empty_var->var_part[0].loc_chain = NULL;
+ empty_var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (empty_var) = VAR_LOC_1PAUX (old_var);
+ VAR_LOC_1PAUX (old_var) = NULL;
}
+ variable_was_changed (empty_var, NULL);
+ /* Continue traversing the hash table. */
+ return 1;
+ }
+ /* Update cur_loc and one-part auxiliary data, before new_var goes
+ through variable_was_changed. */
+ if (old_var != new_var && new_var->onepart)
+ {
+ gcc_checking_assert (VAR_LOC_1PAUX (new_var) == NULL);
+ VAR_LOC_1PAUX (new_var) = VAR_LOC_1PAUX (old_var);
+ VAR_LOC_1PAUX (old_var) = NULL;
+ new_var->var_part[0].cur_loc = old_var->var_part[0].cur_loc;
}
+ if (variable_different_p (old_var, new_var))
+ variable_was_changed (new_var, NULL);
/* Continue traversing the hash table. */
return 1;
@@ -8033,15 +8508,6 @@ emit_notes_for_differences_2 (void **slot, void *data)
if (!old_var)
{
int i;
- /* Variable has appeared. */
- if (dv_onepart_p (new_var->dv))
- {
- location_chain lc;
-
- gcc_assert (new_var->n_var_parts == 1);
- for (lc = new_var->var_part[0].loc_chain; lc; lc = lc->next)
- add_value_chains (new_var->dv, lc->loc);
- }
for (i = 0; i < new_var->n_var_parts; i++)
new_var->var_part[i].cur_loc = NULL;
variable_was_changed (new_var, NULL);
@@ -8111,7 +8577,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
{
XEXP (XEXP (*p, 0), 1)
= vt_expand_loc (XEXP (XEXP (*p, 0), 1),
- shared_hash_htab (set->vars), true);
+ shared_hash_htab (set->vars));
/* If expansion is successful, keep it in the list. */
if (XEXP (XEXP (*p, 0), 1))
p = &XEXP (*p, 1);
@@ -8412,15 +8878,9 @@ vt_emit_notes (void)
emit_notes = true;
if (MAY_HAVE_DEBUG_INSNS)
- {
- unsigned int i;
- rtx val;
-
- FOR_EACH_VEC_ELT (rtx, preserved_values, i, val)
- add_cselib_value_chains (dv_from_value (val));
- changed_variables_stack = VEC_alloc (variable, heap, 40);
- changed_values_stack = VEC_alloc (rtx, heap, 40);
- }
+ dropped_values = htab_create (cselib_get_next_uid () * 2,
+ variable_htab_hash, variable_htab_eq,
+ variable_htab_free);
dataflow_set_init (&cur);
@@ -8441,23 +8901,11 @@ vt_emit_notes (void)
htab_traverse (shared_hash_htab (cur.vars),
emit_notes_for_differences_1,
shared_hash_htab (empty_shared_hash));
- if (MAY_HAVE_DEBUG_INSNS)
- {
- unsigned int i;
- rtx val;
-
- FOR_EACH_VEC_ELT (rtx, preserved_values, i, val)
- remove_cselib_value_chains (dv_from_value (val));
- gcc_assert (htab_elements (value_chains) == 0);
- }
#endif
dataflow_set_destroy (&cur);
if (MAY_HAVE_DEBUG_INSNS)
- {
- VEC_free (variable, heap, changed_variables_stack);
- VEC_free (rtx, heap, changed_values_stack);
- }
+ htab_delete (dropped_values);
emit_notes = false;
}
@@ -8489,36 +8937,27 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
return false;
}
-/* Helper function for vt_add_function_parameter. RTL is
- the expression and VAL corresponding cselib_val pointer
- for which ENTRY_VALUE should be created. */
+/* Mark the value for the ENTRY_VALUE of RTL as equivalent to EQVAL in
+ OUT. */
static void
-create_entry_value (rtx rtl, cselib_val *val)
-{
- cselib_val *val2;
- struct elt_loc_list *el;
- el = (struct elt_loc_list *) ggc_alloc_cleared_atomic (sizeof (*el));
- el->loc = gen_rtx_ENTRY_VALUE (GET_MODE (rtl));
- ENTRY_VALUE_EXP (el->loc) = rtl;
- val2 = cselib_lookup_from_insn (el->loc, GET_MODE (rtl), true,
- VOIDmode, get_insns ());
- el->next = val->locs;
- el->setting_insn = get_insns ();
- val->locs = el;
- if (val2
- && val2 != val
- && val2->locs
- && rtx_equal_p (val2->locs->loc, el->loc))
- {
- struct elt_loc_list *el2;
-
- preserve_value (val2);
- el2 = (struct elt_loc_list *) ggc_alloc_cleared_atomic (sizeof (*el2));
- el2->next = val2->locs;
- el2->loc = val->val_rtx;
- el2->setting_insn = get_insns ();
- val2->locs = el2;
+create_entry_value (dataflow_set *out, rtx eqval, rtx rtl)
+{
+ rtx ev = gen_rtx_ENTRY_VALUE (GET_MODE (rtl));
+ cselib_val *val;
+
+ ENTRY_VALUE_EXP (ev) = rtl;
+
+ val = cselib_lookup_from_insn (ev, GET_MODE (ev), true,
+ VOIDmode, get_insns ());
+
+ if (val->val_rtx != eqval)
+ {
+ preserve_value (val);
+ set_variable_part (out, val->val_rtx, dv_from_value (eqval), 0,
+ VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
+ set_variable_part (out, eqval, dv_from_value (val->val_rtx), 0,
+ VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
}
}
@@ -8678,20 +9117,22 @@ vt_add_function_parameter (tree parm)
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
if (dv_is_value_p (dv))
{
- cselib_val *val = CSELIB_VAL_PTR (dv_as_value (dv));
- create_entry_value (incoming, val);
+ create_entry_value (out, dv_as_value (dv), incoming);
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))
{
enum machine_mode indmode
= TYPE_MODE (TREE_TYPE (TREE_TYPE (parm)));
rtx mem = gen_rtx_MEM (indmode, incoming);
- val = cselib_lookup_from_insn (mem, indmode, true,
- VOIDmode, get_insns ());
+ cselib_val *val = cselib_lookup_from_insn (mem, indmode, true,
+ VOIDmode,
+ get_insns ());
if (val)
{
preserve_value (val);
- create_entry_value (mem, val);
+ set_variable_part (out, mem, dv_from_value (val->val_rtx), 0,
+ VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
+ create_entry_value (out, val->val_rtx, mem);
}
}
}
@@ -8755,23 +9196,6 @@ fp_setter (rtx insn)
return false;
}
-/* Gather all registers used for passing arguments to other functions
- called from the current routine. */
-
-static void
-note_register_arguments (rtx insn)
-{
- rtx link, x;
-
- for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == USE)
- {
- x = XEXP (XEXP (link, 0), 0);
- if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
- SET_HARD_REG_BIT (argument_reg_set, REGNO (x));
- }
-}
-
/* Initialize cfa_base_rtx, create a preserved VALUE for it and
ensure it isn't flushed during cselib_reset_table.
Can be called only if frame_pointer_rtx resp. arg_pointer_rtx
@@ -8843,14 +9267,6 @@ vt_initialize (void)
variable_htab_free);
changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
variable_htab_free);
- if (MAY_HAVE_DEBUG_INSNS)
- {
- value_chain_pool = create_alloc_pool ("value_chain_def pool",
- sizeof (struct value_chain_def),
- 1024);
- value_chains = htab_create (32, value_chain_htab_hash,
- value_chain_htab_eq, NULL);
- }
/* Init the IN and OUT sets. */
FOR_ALL_BB (bb)
@@ -8876,8 +9292,6 @@ vt_initialize (void)
valvar_pool = NULL;
}
- CLEAR_HARD_REG_SET (argument_reg_set);
-
/* In order to factor out the adjustments made to the stack pointer or to
the hard frame pointer and thus be able to use DW_OP_fbreg operations
instead of individual location lists, we're going to rewrite MEMs based
@@ -8962,14 +9376,6 @@ vt_initialize (void)
}
}
- if (frame_pointer_needed)
- {
- rtx insn;
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (CALL_P (insn))
- note_register_arguments (insn);
- }
-
hard_frame_pointer_adjustment = -1;
vt_add_function_parameters ();
@@ -9155,8 +9561,6 @@ vt_finalize (void)
if (MAY_HAVE_DEBUG_INSNS)
{
- htab_delete (value_chains);
- free_alloc_pool (value_chain_pool);
free_alloc_pool (valvar_pool);
VEC_free (rtx, heap, preserved_values);
cselib_finish ();
@@ -9164,7 +9568,9 @@ vt_finalize (void)
scratch_regs = NULL;
}
+#ifdef HAVE_window_save
VEC_free (parm_reg_t, gc, windowed_parm_regs);
+#endif
if (vui_vec)
XDELETEVEC (vui_vec);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9b4dfad5cbb..d0de2136bd8 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -2104,7 +2104,8 @@ incorporeal_function_p (tree decl)
const char *name;
if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
+ && (DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA
+ || DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA_WITH_ALIGN))
return true;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
@@ -3118,7 +3119,7 @@ build_constant_desc (tree exp)
SET_SYMBOL_REF_DECL (symbol, decl);
TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;
- rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
+ rtl = gen_const_mem (TYPE_MODE (TREE_TYPE (exp)), symbol);
set_mem_attributes (rtl, exp, 1);
set_mem_alias_set (rtl, 0);
set_mem_alias_set (rtl, const_alias_set);
diff --git a/gcc/varpool.c b/gcc/varpool.c
index d223779a5c1..e342a9109d9 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -703,9 +703,11 @@ varpool_create_variable_alias (tree alias, tree decl)
gcc_assert (TREE_CODE (alias) == VAR_DECL);
alias_node = varpool_node (alias);
alias_node->alias = 1;
- alias_node->finalized = 1;
+ if (!DECL_EXTERNAL (alias))
+ alias_node->finalized = 1;
alias_node->alias_of = decl;
- if (decide_is_variable_needed (alias_node, alias)
+ if ((!DECL_EXTERNAL (alias)
+ && decide_is_variable_needed (alias_node, alias))
|| alias_node->needed)
varpool_mark_needed_node (alias_node);
return alias_node;
diff --git a/gnattools/ChangeLog b/gnattools/ChangeLog
index 9bcd6213230..e9a7a8be14e 100644
--- a/gnattools/ChangeLog
+++ b/gnattools/ChangeLog
@@ -1,3 +1,13 @@
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.in (LOOSE_WARN): Delete.
+ (GCC_WARN_CFLAGS): Set to -W -Wall.
+ (TOOLS_FLAGS_TO_PASS_1): Delete.
+ (TOOLS_FLAGS_TO_PASS_1re): Rename into...
+ (TOOLS_FLAGS_TO_PASS_RE): ...this.
+ (gnattools-native): Use TOOLS_FLAGS_TO_PASS_NATIVE.
+ (regnattools): Use TOOLS_FLAGS_TO_PASS_RE.
+
2011-07-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR target/39150
diff --git a/gnattools/Makefile.in b/gnattools/Makefile.in
index 3718b30593f..794d374e75e 100644
--- a/gnattools/Makefile.in
+++ b/gnattools/Makefile.in
@@ -44,8 +44,7 @@ PWD_COMMAND = $${PWDCMD-pwd}
# The tedious process of getting CFLAGS right.
CFLAGS=-g
-LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
-GCC_WARN_CFLAGS = $(LOOSE_WARN)
+GCC_WARN_CFLAGS = -W -Wall
WARN_CFLAGS = @warn_cflags@
ADA_CFLAGS=@ADA_CFLAGS@
@@ -64,8 +63,8 @@ INCLUDES_FOR_SUBDIR = -I. -I.. -I../.. -I$(fsrcdir)/ada -I$(fsrcdir)/config \
-I$(fsrcdir)/../include -I$(fsrcdir)
ADA_INCLUDES_FOR_SUBDIR = -I. -I$(fsrcdir)/ada
-# Variables for gnattools1, native
-TOOLS_FLAGS_TO_PASS_1= \
+# Variables for gnattools, native
+TOOLS_FLAGS_TO_PASS_NATIVE= \
"CC=../../xgcc -B../../" \
"CFLAGS=$(CFLAGS) $(WARN_CFLAGS)" \
"LDFLAGS=$(LDFLAGS)" \
@@ -76,11 +75,13 @@ TOOLS_FLAGS_TO_PASS_1= \
"exeext=$(exeext)" \
"fsrcdir=$(fsrcdir)" \
"srcdir=$(fsrcdir)" \
+ "GNATMAKE=../../gnatmake" \
+ "GNATLINK=../../gnatlink" \
"GNATBIND=../../gnatbind" \
"TOOLSCASE=native"
# Variables for regnattools
-TOOLS_FLAGS_TO_PASS_1re= \
+TOOLS_FLAGS_TO_PASS_RE= \
"CC=../../xgcc -B../../" \
"CFLAGS=$(CFLAGS)" \
"ADAFLAGS=$(ADAFLAGS)" \
@@ -93,24 +94,7 @@ TOOLS_FLAGS_TO_PASS_1re= \
"GNATMAKE=../../gnatmake" \
"GNATLINK=../../gnatlink" \
"GNATBIND=../../gnatbind" \
- "TOOLSCASE=cross" \
- "INCLUDES="
-
-# Variables for gnattools2, native
-TOOLS_FLAGS_TO_PASS_NATIVE= \
- "CC=../../xgcc -B../../" \
- "CFLAGS=$(CFLAGS)" \
- "ADAFLAGS=$(ADAFLAGS)" \
- "ADA_CFLAGS=$(ADA_CFLAGS)" \
- "INCLUDES=$(INCLUDES_FOR_SUBDIR)" \
- "ADA_INCLUDES=-I../rts $(ADA_INCLUDES_FOR_SUBDIR)" \
- "exeext=$(exeext)" \
- "fsrcdir=$(fsrcdir)" \
- "srcdir=$(fsrcdir)" \
- "GNATMAKE=../../gnatmake" \
- "GNATLINK=../../gnatlink" \
- "GNATBIND=../../gnatbind" \
- "TOOLSCASE=native"
+ "TOOLSCASE=cross"
# Variables for gnattools, cross
TOOLS_FLAGS_TO_PASS_CROSS= \
@@ -177,7 +161,7 @@ $(GCC_DIR)/stamp-tools:
gnattools-native: $(GCC_DIR)/stamp-tools $(GCC_DIR)/stamp-gnatlib-rts
# gnattools1
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
- $(TOOLS_FLAGS_TO_PASS_1) \
+ $(TOOLS_FLAGS_TO_PASS_NATIVE) \
../../gnatmake$(exeext) ../../gnatlink$(exeext)
# gnattools2
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
@@ -189,7 +173,7 @@ gnattools-native: $(GCC_DIR)/stamp-tools $(GCC_DIR)/stamp-gnatlib-rts
regnattools: $(GCC_DIR)/stamp-gnatlib-rts
# gnattools1-re
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
- $(TOOLS_FLAGS_TO_PASS_1re) \
+ $(TOOLS_FLAGS_TO_PASS_RE) INCLUDES="" \
gnatmake-re gnatlink-re
# gnattools2
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
diff --git a/libada/ChangeLog b/libada/ChangeLog
index 689e9fb1a32..fbcff774051 100644
--- a/libada/ChangeLog
+++ b/libada/ChangeLog
@@ -1,3 +1,14 @@
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.in (LOOSE_WARN): Delete.
+ (GCC_WARN_CFLAGS): Likewise.
+ (WARN_CFLAGS): Likewise.
+ (GNATLIBFLAGS): Add -nostdinc.
+ (GNATLIBCFLAGS_FOR_C): Add -W -Wall.
+ (LIBADA_FLAGS_TO_PASS): Remove WARN_CFLAGS.
+ * configure.ac (warn_cflags): Delete.
+ * configure: Regenerate.
+
2011-08-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac: Include ../config/picflag.m4.
diff --git a/libada/Makefile.in b/libada/Makefile.in
index 6f3df38c322..86aff529dbd 100644
--- a/libada/Makefile.in
+++ b/libada/Makefile.in
@@ -45,21 +45,17 @@ AWK=@AWK@
# Variables for the user (or the top level) to override.
objext=.o
-GNATLIBFLAGS= -W -Wall -gnatpg
THREAD_KIND=native
TRACE=no
LDFLAGS=
# The tedious process of getting CFLAGS right.
CFLAGS=-g
-LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
-GCC_WARN_CFLAGS = $(LOOSE_WARN)
-WARN_CFLAGS = @warn_cflags@
-
PICFLAG = @PICFLAG@
+GNATLIBFLAGS= -W -Wall -gnatpg -nostdinc
GNATLIBCFLAGS= -g -O2
-GNATLIBCFLAGS_FOR_C = $(GNATLIBCFLAGS) $(PICFLAG) -fexceptions \
- -DIN_RTS @have_getipinfo@
+GNATLIBCFLAGS_FOR_C = -W -Wall $(GNATLIBCFLAGS) $(PICFLAG) \
+ -fexceptions -DIN_RTS @have_getipinfo@
host_subdir = @host_subdir@
GCC_DIR=$(MULTIBUILDTOP)../../$(host_subdir)/gcc
@@ -91,7 +87,7 @@ LIBADA_FLAGS_TO_PASS = \
"exeext=.exeext.should.not.be.used " \
'CC=the.host.compiler.should.not.be.needed' \
"GCC_FOR_TARGET=$(CC)" \
- "CFLAGS=$(CFLAGS) $(WARN_CFLAGS)"
+ "CFLAGS=$(CFLAGS)"
# Rules to build gnatlib.
.PHONY: gnatlib gnatlib-plain gnatlib-sjlj gnatlib-zcx gnatlib-shared oscons
diff --git a/libada/configure b/libada/configure
index c0a294fdd0c..1e0ceefc86a 100755
--- a/libada/configure
+++ b/libada/configure
@@ -553,7 +553,6 @@ PACKAGE_URL=
ac_unique_file="Makefile.in"
ac_subst_vars='LTLIBOBJS
LIBOBJS
-warn_cflags
have_getipinfo
default_gnatlib_target
LN_S
@@ -3007,12 +3006,6 @@ if test x$have_unwind_getipinfo = xyes; then
fi
-warn_cflags=
-if test "x$GCC" = "xyes"; then
- warn_cflags='$(GCC_WARN_CFLAGS)'
-fi
-
-
# Output: create a Makefile.
ac_config_files="$ac_config_files Makefile"
diff --git a/libada/configure.ac b/libada/configure.ac
index f9b9c5ab3b0..1e3760cbe4c 100644
--- a/libada/configure.ac
+++ b/libada/configure.ac
@@ -144,12 +144,6 @@ if test x$have_unwind_getipinfo = xyes; then
fi
AC_SUBST(have_getipinfo)
-warn_cflags=
-if test "x$GCC" = "xyes"; then
- warn_cflags='$(GCC_WARN_CFLAGS)'
-fi
-AC_SUBST(warn_cflags)
-
# Output: create a Makefile.
AC_CONFIG_FILES([Makefile])
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 4ecda03cfec..bbb4085f012 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,241 @@
+2011-10-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50760
+ * include/line-map.h (struct linemap_stats): Change the type of
+ the members from size_t to long.
+ * macro.c (macro_arg_token_iter_init): Unconditionally initialize
+ iter->location_ptr.
+
+2011-10-17 Dodji Seketeli <dodji@redhat.com>
+
+ * line-map.c (linemap_macro_map_loc_to_exp_point): Avoid setting a
+ variable without using it if ENABLE_CHECKING is not defined. Mark
+ the LOCATION parameter as being unused.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/line-map.h (struct line_maps::alloced_size_for_request):
+ New member.
+ * line-map.c (new_linemap): Use set->alloced_size_for_request to
+ get the actual allocated size of line maps.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * line-map.h (struct linemap_stats): Declare new struct.
+ (linemap_get_statistics): Declare ...
+ * line-map.c (linemap_get_statistics): ... new function.
+ * macro.c (num_expanded_macros_counter, num_macro_tokens_counter):
+ Declare new counters.
+ (enter_macro_context, replace_args): Update
+ num_macro_tokens_counter.
+ (cpp_get_token_1): Update num_expanded_macros_counter.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/cpplib.h (struct cpp_options)<debug>: New struct member.
+ * include/line-map.h (linemap_dump_location): Declare ...
+ * line-map.c (linemap_dump_location): ... new function.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/cpplib.h (struct cpp_options)<track_macro_expansion>:
+ New option.
+ * internal.h (struct macro_context): New struct.
+ (enum context_tokens_kind): New enum.
+ (struct cpp_context)<tokens_kind>: New member of type enum
+ context_tokens_kind.
+ (struct cpp_context)<macro>: Remove this. Replace it with an enum
+ of macro and macro_context.
+ (struct cpp_context)<direct_p>: Remove.
+ (_cpp_remaining_tokens_num_in_context): Declare new function.
+ * directives.c (destringize_and_run): Adjust.
+ * lex.c (_cpp_remaining_tokens_num_in_context)
+ (_cpp_token_from_context_at): Define new functions
+ (cpp_peek_token): Use them.
+ * init.c (cpp_create_reader): Initialize the base context to zero.
+ (_cpp_token_from_context_at): Define new static function.
+ (cpp_peek_token): Use new _cpp_remaining_tokens_num_in_context and
+ _cpp_token_from_context_at.
+ * macro.c (struct macro_arg)<virt_locs, expanded_virt_locs>: New
+ members.
+ (enum macro_arg_token_kind): New enum.
+ (struct macro_arg_token_iter): New struct.
+ (maybe_adjust_loc_for_trad_cpp, push_extended_tokens_context)
+ (alloc_expanded_arg_mem, ensure_expanded_arg_room)
+ (delete_macro_args, set_arg_token, get_arg_token_location)
+ (arg_token_ptr_at, macro_arg_token_iter_init)
+ (macro_arg_token_iter_get_token)
+ (macro_arg_token_iter_get_location, macro_arg_token_iter_forward)
+ (expanded_token_index, tokens_buff_new, tokens_buff_count)
+ (tokens_buff_last_token_ptr, tokens_buff_put_token_to)
+ (tokens_buff_add_token, tokens_buff_remove_last_token)
+ (reached_end_of_context, consume_next_token_from_context): New
+ static functions.
+ (cpp_get_token_1): New static function. Split and extended from
+ cpp_get_token. Use reached_end_of_context and
+ consume_next_token_from_context. Unify its return point. Move
+ the location tweaking from cpp_get_token_with_location in here.
+ (cpp_get_token): Use cpp_get_token_1
+ (stringify_arg): Use the new arg_token_at.
+ (paste_all_tokens): Support tokens coming from extended tokens
+ contexts.
+ (collect_args): Return the number of collected arguments, by
+ parameter. Store virtual locations of tokens that constitute the
+ collected args.
+ (funlike_invocation_p): Return the number of collected arguments,
+ by parameter.
+ (enter_macro_context): Add a parameter for macro expansion point.
+ Pass it to replace_args and to the "used" cpp callback. Get the
+ number of function-like macro arguments from funlike_invocation_p,
+ pass it to the new delete_macro_args to free the memory used by
+ macro args. When -ftrack-macro-expansion is in effect, for macros
+ that have no arguments, create a macro map for the macro expansion
+ and use it to allocate proper virtual locations for tokens
+ resulting from the expansion. Push an extended tokens context
+ containing the tokens resulting from macro expansion and their
+ virtual locations.
+ (replace_args): Rename the different variables named 'count' into
+ variables with more meaningful names. Create a macro map;
+ allocate virtual locations of tokens resulting from this
+ expansion. Use macro_arg_token_iter to iterate over tokens of a
+ given macro. Handle the case of the argument of
+ -ftrack-macro-expansion being < 2. Don't free macro arguments
+ memory resulting from expand_arg here, as these are freed by the
+ caller of replace_arg using delete_macro_args now. Push extended
+ token context.
+ (next_context, push_ptoken_context, _cpp_push_token_context)
+ (_cpp_push_text_context): Properly initialize the context.
+ (expand_arg): Use the new alloc_expanded_arg_mem,
+ push_extended_tokens_context, cpp_get_token_1, and set_arg_token.
+ (_cpp_pop_context): Really free the memory held by the context.
+ Handle freeing memory used by extended tokens contexts.
+ (cpp_get_token_with_location): Use cpp_get_token_1.
+ (cpp_sys_macro_p): Adjust.
+ (_cpp_backup_tokens): Support the new kinds of token contexts.
+ * traditional.c (recursive_macro): Adjust.
+
+2011-10-15 Tom Tromey <tromey@redhat>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/line-map.h (enum lc_reason)<LC_ENTER_MACRO>: New enum
+ member.
+ (MAX_SOURCE_LOCATION): New constant.
+ (struct line_map_ordinary, struct line_map_macro): New structs.
+ (struct line_map): Turn this into a union of the two above. Add
+ comments.
+ (struct maps_info): New struct.
+ (struct line_maps)<info_ordinary, info_macro>: Two new fields.
+ These now carry the map information that was previously scattered
+ in struct line_maps.
+ (struct map_info::allocated): Fix comment.
+ (MAP_START_LOCATION, ORDINARY_MAP_FILE_NAME)
+ (ORDINARY_MAP_STARTING_LINE_NUMBER)
+ (ORDINARY_MAP_INCLUDER_FILE_INDEX)
+ (ORDINARY_MAP_IN_SYSTEM_HEADER_P)
+ (ORDINARY_MAP_NUMBER_OF_COLUMN_BITS, MACRO_MAP_MACRO)
+ (MACRO_MAP_NUM_MACRO_TOKENS MACRO_MAP_LOCATIONS)
+ (MACRO_MAP_EXPANSION_POINT_LOCATION)
+ (LOCATION_POSSIBLY_IN_MACRO_MAP_P, LINEMAPS_MAP_INFO)
+ (LINEMAPS_MAPS, LINEMAPS_ALLOCATE, LINEMAPS_USED, LINEMAPS_CACHE)
+ (LINEMAPS_LAST_MAP, LINEMAPS_LAST_ALLOCATED_MAP)
+ (LINEMAPS_ORDINARY_MAPS, LINEMAPS_ORDINARY_ALLOCATED)
+ (LINEMAPS_ORDINARY_USED, LINEMAPS_ORDINARY_CACHE)
+ (LINEMAPS_LAST_ORDINARY_MAP, LINEMAPS_LAST_ALLOCATED_ORDINARY_MAP)
+ (LINEMAPS_MACRO_MAPS, LINEMAPS_MACRO_ALLOCATED)
+ (LINEMAPS_MACRO_USED, LINEMAPS_MACRO_CACHE)
+ (LINEMAPS_LAST_MACRO_MAP, LINEMAPS_LAST_ALLOCATED_MACRO_MAP)
+ (LINEMAPS_MAP_AT, LINEMAPS_ORDINARY_MAP_AT)
+ (LINEMAPS_MACRO_MAP_AT): New accessors for ordinary and macro map
+ information.
+ (linemap_check_ordinary, linemap_assert)
+ (linemap_location_before_p): New macros.
+ (linemap_position_for_line_and_column)
+ (linemap_tracks_macro_expansion_locs_p, linemap_add_macro_token)
+ (linemap_macro_expansion_map_p)
+ (linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_once)
+ (linemap_macro_map_loc_to_exp_point, linemap_step_out_once)
+ (linemap_get_source_line linemap_get_source_column)
+ (linemap_map_get_macro_name, linemap_get_file_path)
+ (linemap_location_in_system_header_p)
+ (linemap_location_from_macro_expansion_p): Declare new functions.
+ (SOURCE_LINE, SOURCE_COLUMN, LAST_SOURCE_LINE_LOCATION)
+ (LINEMAP_FILE, LINEMAP_LINE, LINEMAP_SYSP): Assert that this
+ accessors act on ordinary maps only.
+ (INCLUDED_FROM): Return NULL for main files; use the new
+ accessors.
+ (LINEMAP_POSITION_FOR_COLUMN): Use the new accessors.
+ (struct expanded_location): Move here from gcc/input.h
+ (linemap_resolve_location, linemap_expand_location)
+ (linemap_expand_location_full): Declare new functions.
+ * line-map.c: Include cpplib.h, internal.h
+ (linemap_enter_macro, linemap_add_macro_token)
+ (linemap_get_expansion_line, linemap_get_expansion_filename): New
+ functions that are private to libcpp.
+ (linemap_assert): New macro.
+ (linemap_macro_loc_to_exp_point, linemap_macro_loc_to_exp_point)
+ (linemap_macro_loc_unwind, linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_toward_spelling)
+ (linemap_macro_map_loc_to_exp_point)
+ (first_map_in_common_1, first_map_in_common): New static
+ functions.
+ (new_linemap): Define new static functions. Extracted and
+ enhanced from ...
+ (linemap_add): ... here. Use linemap_assert in lieu of abort
+ previously.
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_add_macro_token, linemap_macro_expansion_map_p)
+ (linemap_check_ordinary, linemap_macro_map_loc_to_exp_point)
+ (linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_once)
+ (linemap_step_out_once, linemap_map_get_index)
+ (linemap_get_source_line,linemap_get_source_column)
+ (linemap_get_file_path, linemap_map_get_macro_name)
+ (linemap_location_in_system_header_p)
+ (linemap_location_originated_from_system_header_p)
+ (linemap_location_from_macro_expansion_p)
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_resolve_location, linemap_expand_location)
+ (linemap_expand_location_full)
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_position_for_line_and_column, linemap_compare_locations):
+ Define new public functions.
+ (linemap_init): Initialize ordinary and macro maps information in
+ the map set.
+ (linemap_check_files_exited): Use the new accessors.
+ (linemap_free): Remove this dead code.
+ (linemap_line_start): Assert this uses an ordinary map. Adjust to
+ use the new ordinary map accessors and data structures. Don't
+ overflow past the lowest possible macro token's location.
+ (linemap_position_for_column): Assert the ordinary maps of the map
+ set are really ordinary. Use ordinary map accessors.
+ (linemap_lookup): Keep the same logic but generalize to allow
+ lookup of both ordinary and macro maps. Do not crash when called
+ with an empty line table.
+ * directives-only.c (_cpp_preprocess_dir_only): Adjust to use the
+ new API of line-map.h.
+ * directives.c (start_directive, do_line, do_linemarker)
+ (do_linemarker): Likewise.
+ * files.c (_cpp_find_file, _cpp_stack_include, open_file_failed)
+ (make_cpp_dir, cpp_make_system_header): Likewise.
+ * init.c (cpp_read_main_file): Likewise.
+ * internal.h (CPP_INCREMENT_LINE): Likewise.
+ (linemap_enter_macro, linemap_add_macro_token)
+ (linemap_get_expansion_line, linemap_get_expansion_filename): New
+ functions private to libcpp.
+ * lex.c (_cpp_process_line_notes, _cpp_skip_block_comment)
+ (skip_line_comment, skip_whitespace, lex_raw_string)
+ (_cpp_lex_direct): Likewise.
+ * macro.c (_cpp_builtin_macro_text): Likewise.
+ (_cpp_aligned_alloc): Initialize the new name member of the macro.
+ * traditional.c (copy_comment, _cpp_scan_out_logical_line):
+ Likewise.
+ * errors.c (cpp_diagnostic): Adjust to new linemap API.
+
2011-08-28 Dodji Seketeli <dodji@redhat.com>
* line-map.c (linemap_add): Assert that reason must not be
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 83d4a0e8d7f..0510c6e3a8e 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -1,7 +1,7 @@
/* CPP Library. (Directive handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -884,14 +884,14 @@ static void
do_line (cpp_reader *pfile)
{
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
/* skip_rest_of_line() may cause line table to be realloc()ed so note down
sysp right now. */
- unsigned char map_sysp = map->sysp;
+ unsigned char map_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
const cpp_token *token;
- const char *new_file = map->to_file;
+ const char *new_file = ORDINARY_MAP_FILE_NAME (map);
linenum_type new_lineno;
/* C99 raised the minimum limit on #line numbers. */
@@ -946,11 +946,11 @@ static void
do_linemarker (cpp_reader *pfile)
{
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
const cpp_token *token;
- const char *new_file = map->to_file;
+ const char *new_file = ORDINARY_MAP_FILE_NAME (map);
linenum_type new_lineno;
- unsigned int new_sysp = map->sysp;
+ unsigned int new_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
enum lc_reason reason = LC_RENAME_VERBATIM;
int flag;
bool wrapped;
@@ -1038,7 +1038,9 @@ _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason,
const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
to_file, file_line);
if (map != NULL)
- linemap_line_start (pfile->line_table, map->to_line, 127);
+ linemap_line_start (pfile->line_table,
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map),
+ 127);
if (pfile->cb.file_change)
pfile->cb.file_change (pfile, map);
@@ -1740,7 +1742,7 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in)
saved_cur_run = pfile->cur_run;
pfile->context = XNEW (cpp_context);
- pfile->context->macro = 0;
+ pfile->context->c.macro = 0;
pfile->context->prev = 0;
pfile->context->next = 0;
diff --git a/libcpp/files.c b/libcpp/files.c
index d2c6b8bdecf..fad8b75fe57 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -1220,13 +1220,12 @@ cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc)
{
int flags = 0;
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used-1];
-
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
/* 1 = system header, 2 = system header to be treated as C. */
if (syshdr)
flags = 1 + (externc != 0);
pfile->buffer->sysp = flags;
- _cpp_do_file_change (pfile, LC_RENAME, map->to_file,
+ _cpp_do_file_change (pfile, LC_RENAME, ORDINARY_MAP_FILE_NAME (map),
SOURCE_LINE (map, pfile->line_table->highest_line), flags);
}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 0e90821072f..825bf2fc6ff 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -392,6 +392,18 @@ struct cpp_options
/* Nonzero means we're looking at already preprocessed code, so don't
bother trying to do macro expansion and whatnot. */
unsigned char preprocessed;
+
+ /* Nonzero means we are going to emit debugging logs during
+ preprocessing. */
+ unsigned char debug;
+
+ /* Nonzero means we are tracking locations of tokens involved in
+ macro expansion. 1 Means we track the location in degraded mode
+ where we do not track locations of tokens resulting from the
+ expansion of arguments of function-like macro. 2 Means we do
+ track all macro expansions. This last option is the one that
+ consumes the highest amount of memory. */
+ unsigned char track_macro_expansion;
/* Nonzero means handle C++ alternate operator names. */
unsigned char operator_names;
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 3c84035e95f..ef98f5935b3 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -1,5 +1,5 @@
/* Map logical line numbers to (source file, line number) pairs.
- Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010
+ Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -27,13 +27,22 @@ along with this program; see the file COPYING3. If not see
#define GTY(x) /* nothing */
#endif
-/* Reason for adding a line change with add_line_map (). LC_ENTER is
+/* Reason for creating a new line map with linemap_add. LC_ENTER is
when including a new file, e.g. a #include directive in C.
LC_LEAVE is when reaching a file's end. LC_RENAME is when a file
name or line number changes for neither of the above reasons
(e.g. a #line directive in C); LC_RENAME_VERBATIM is like LC_RENAME
- but a filename of "" is not specially interpreted as standard input. */
-enum lc_reason {LC_ENTER = 0, LC_LEAVE, LC_RENAME, LC_RENAME_VERBATIM};
+ but a filename of "" is not specially interpreted as standard
+ input. LC_ENTER_MACRO is when a macro expansion is about to start. */
+enum lc_reason
+{
+ LC_ENTER = 0,
+ LC_LEAVE,
+ LC_RENAME,
+ LC_RENAME_VERBATIM,
+ LC_ENTER_MACRO
+ /* FIXME: add support for stringize and paste. */
+};
/* The type of line numbers. */
typedef unsigned int linenum_type;
@@ -44,37 +53,218 @@ typedef unsigned int source_location;
/* Memory allocation function typedef. Works like xrealloc. */
typedef void *(*line_map_realloc) (void *, size_t);
-/* Physical source file TO_FILE at line TO_LINE at column 0 is represented
+/* Memory allocator function that returns the actual allocated size,
+ for a given requested allocation. */
+typedef size_t (*line_map_round_alloc_size_func) (size_t);
+
+/* An ordinary line map encodes physical source locations. Those
+ physical source locations are called "spelling locations".
+
+ Physical source file TO_FILE at line TO_LINE at column 0 is represented
by the logical START_LOCATION. TO_LINE+L at column C is represented by
START_LOCATION+(L*(1<<column_bits))+C, as long as C<(1<<column_bits),
and the result_location is less than the next line_map's start_location.
(The top line is line 1 and the leftmost column is column 1; line/column 0
means "entire file/line" or "unknown line/column" or "not applicable".)
- INCLUDED_FROM is an index into the set that gives the line mapping
- at whose end the current one was included. File(s) at the bottom
- of the include stack have this set to -1. REASON is the reason for
- creation of this line map, SYSP is one for a system header, two for
- a C system header file that therefore needs to be extern "C"
- protected in C++, and zero otherwise. */
-struct GTY(()) line_map {
+
+ The highest possible source location is MAX_SOURCE_LOCATION. */
+struct GTY(()) line_map_ordinary {
const char *to_file;
linenum_type to_line;
- source_location start_location;
+
+ /* An index into the set that gives the line mapping at whose end
+ the current one was included. File(s) at the bottom of the
+ include stack have this set to -1. */
int included_from;
- ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
- /* The sysp field isn't really needed now that it's in cpp_buffer. */
+
+ /* SYSP is one for a system header, two for a C system header file
+ that therefore needs to be extern "C" protected in C++, and zero
+ otherwise. This field isn't really needed now that it's in
+ cpp_buffer. */
unsigned char sysp;
+
/* Number of the low-order source_location bits used for a column number. */
unsigned int column_bits : 8;
};
-/* A set of chronological line_map structures. */
-struct GTY(()) line_maps {
+/* This is the highest possible source location encoded within an
+ ordinary or macro map. */
+#define MAX_SOURCE_LOCATION 0xFFFFFFFF
+
+struct cpp_hashnode;
+
+/* A macro line map encodes location of tokens coming from a macro
+ expansion.
+
+ Please note that this struct line_map_macro is a field of struct
+ line_map below, go read the comments of struct line_map below and
+ then come back here.
+
+ The offset from START_LOCATION is used to index into
+ MACRO_LOCATIONS; this holds the original location of the token. */
+struct GTY(()) line_map_macro {
+ /* The cpp macro which expansion gave birth to this macro map. */
+ struct cpp_hashnode * GTY ((nested_ptr (union tree_node,
+ "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
+ "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL")))
+ macro;
+
+ /* The number of tokens inside the replacement-list of MACRO. */
+ unsigned int n_tokens;
+
+ /* This array of location is actually an array of pairs of
+ locations. The elements inside it thus look like:
+
+ x0,y0, x1,y1, x2,y2, ...., xn,yn.
+
+ where n == n_tokens;
+
+ Remember that these xI,yI are collected when libcpp is about to
+ expand a given macro.
+
+ yI is the location in the macro definition, either of the token
+ itself or of a macro parameter that it replaces.
+
+ Imagine this:
+
+ #define PLUS(A, B) A + B <--- #1
+
+ int a = PLUS (1,2); <--- #2
+
+ There is a macro map for the expansion of PLUS in #2. PLUS is
+ expanded into its expansion-list. The expansion-list is the
+ replacement-list of PLUS where the macro parameters are replaced
+ with their arguments. So the replacement-list of PLUS is made of
+ the tokens:
+
+ A, +, B
+
+ and the expansion-list is made of the tokens:
+
+ 1, +, 2
+
+ Let's consider the case of token "+". Its y1 [yI for I == 1] is
+ its spelling location in #1.
+
+ y0 (thus for token "1") is the spelling location of A in #1.
+
+ And y2 (of token "2") is the spelling location of B in #1.
+
+ When the token is /not/ an argument for a macro, xI is the same
+ location as yI. Otherwise, xI is the location of the token
+ outside this macro expansion. If this macro was expanded from
+ another macro expansion, xI is a virtual location representing
+ the token in that macro expansion; otherwise, it is the spelling
+ location of the token.
+
+ Note that a virtual location is a location returned by
+ linemap_add_macro_token. It encodes the relevant locations (x,y
+ pairs) of that token accross the macro expansions from which it
+ (the token) might come from.
+
+ In the example above x1 (for token "+") is going to be the same
+ as y1. x0 is the spelling location for the argument token "1",
+ and x2 is the spelling location for the argument token "2". */
+ source_location * GTY((length ("2 * %h.n_tokens"))) macro_locations;
+
+ /* This is the location of the expansion point of the current macro
+ map. It's the location of the macro name. That location is held
+ by the map that was current right before the current one. It
+ could have been either a macro or an ordinary map, depending on
+ if we are in a nested expansion context not. */
+ source_location expansion;
+};
+
+/* A line_map encodes a sequence of locations.
+ There are two kinds of maps. Ordinary maps and macro expansion
+ maps, a.k.a macro maps.
+
+ A macro map encodes source locations of tokens that are part of a
+ macro replacement-list, at a macro expansion point. E.g, in:
+
+ #define PLUS(A,B) A + B
+
+ No macro map is going to be created there, because we are not at a
+ macro expansion point. We are at a macro /definition/ point. So the
+ locations of the tokens of the macro replacement-list (i.e, A + B)
+ will be locations in an ordinary map, not a macro map.
+
+ On the other hand, if we later do:
+
+ int a = PLUS (1,2);
+
+ The invocation of PLUS here is a macro expansion. So we are at a
+ macro expansion point. The preprocessor expands PLUS (1,2) and
+ replaces it with the tokens of its replacement-list: 1 + 2. A macro
+ map is going to be created to hold (or rather to map, haha ...) the
+ locations of the tokens 1, + and 2. The macro map also records the
+ location of the expansion point of PLUS. That location is mapped in
+ the map that is active right before the location of the invocation
+ of PLUS. */
+struct GTY(()) line_map {
+ source_location start_location;
+
+ /* The reason for creation of this line map. */
+ ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
+
+ union map_u {
+ struct line_map_ordinary GTY((tag ("0"))) ordinary;
+ struct line_map_macro GTY((tag ("1"))) macro;
+ } GTY((desc ("%1.reason == LC_ENTER_MACRO"))) d;
+};
+
+#define MAP_START_LOCATION(MAP) (MAP)->start_location
+
+#define ORDINARY_MAP_FILE_NAME(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.to_file
+
+#define ORDINARY_MAP_STARTING_LINE_NUMBER(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.to_line
+
+#define ORDINARY_MAP_INCLUDER_FILE_INDEX(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.included_from
+
+#define ORDINARY_MAP_IN_SYSTEM_HEADER_P(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.sysp
+
+#define ORDINARY_MAP_NUMBER_OF_COLUMN_BITS(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.column_bits
+
+#define MACRO_MAP_MACRO(MAP) (MAP)->d.macro.macro
+
+#define MACRO_MAP_NUM_MACRO_TOKENS(MAP) (MAP)->d.macro.n_tokens
+
+#define MACRO_MAP_LOCATIONS(MAP) (MAP)->d.macro.macro_locations
+
+#define MACRO_MAP_EXPANSION_POINT_LOCATION(MAP) (MAP)->d.macro.expansion
+
+/* The abstraction of a set of location maps. There can be several
+ types of location maps. This abstraction contains the attributes
+ that are independent from the type of the map. */
+struct GTY(()) maps_info {
+ /* This array contains the different line maps.
+ A line map is created for the following events:
+ - when a new preprocessing unit start.
+ - when a preprocessing unit ends.
+ - when a macro expansion occurs. */
struct line_map * GTY ((length ("%h.used"))) maps;
+
+ /* The total number of allocated maps. */
unsigned int allocated;
+
+ /* The number of elements used in maps. This number is smaller
+ or equal to ALLOCATED. */
unsigned int used;
unsigned int cache;
+};
+
+/* A set of chronological line_map structures. */
+struct GTY(()) line_maps {
+
+ struct maps_info info_ordinary;
+
+ struct maps_info info_macro;
/* Depth of the include stack, including the current file. */
unsigned int depth;
@@ -95,14 +285,132 @@ struct GTY(()) line_maps {
/* If non-null, the allocator to use when resizing 'maps'. If null,
xrealloc is used. */
line_map_realloc reallocator;
+
+ /* The allocators' function used to know the actual size it
+ allocated, for a certain allocation size requested. */
+ line_map_round_alloc_size_func round_alloc_size;
};
+/* Returns the pointer to the memory region where information about
+ maps are stored in the line table SET. MACRO_MAP_P is a flag
+ telling if we want macro or ordinary maps. */
+#define LINEMAPS_MAP_INFO(SET, MACRO_MAP_P) \
+ ((MACRO_MAP_P) \
+ ? &((SET)->info_macro) \
+ : &((SET)->info_ordinary))
+
+/* Returns the pointer to the memory region where maps are stored in
+ the line table SET. MAP_KIND shall be TRUE if we are interested in
+ macro maps false otherwise. */
+#define LINEMAPS_MAPS(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->maps
+
+/* Returns the number of allocated maps so far. MAP_KIND shall be TRUE
+ if we are interested in macro maps, FALSE otherwise. */
+#define LINEMAPS_ALLOCATED(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->allocated
+
+/* Returns the number of used maps so far. MAP_KIND shall be TRUE if
+ we are interested in macro maps, FALSE otherwise.*/
+#define LINEMAPS_USED(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->used
+
+/* Returns the index of the last map that was looked up with
+ linemap_lookup. MAP_KIND shall be TRUE if we are interested in
+ macro maps, FALSE otherwise. */
+#define LINEMAPS_CACHE(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->cache
+
+/* Return the map at a given index. */
+#define LINEMAPS_MAP_AT(SET, MAP_KIND, INDEX) \
+ (&((LINEMAPS_MAPS (SET, MAP_KIND))[(INDEX)]))
+
+/* Returns the last map used in the line table SET. MAP_KIND
+ shall be TRUE if we are interested in macro maps, FALSE
+ otherwise.*/
+#define LINEMAPS_LAST_MAP(SET, MAP_KIND) \
+ LINEMAPS_MAP_AT (SET, MAP_KIND, (LINEMAPS_USED (SET, MAP_KIND) - 1))
+
+/* Returns the last map that was allocated in the line table SET.
+ MAP_KIND shall be TRUE if we are interested in macro maps, FALSE
+ otherwise.*/
+#define LINEMAPS_LAST_ALLOCATED_MAP(SET, MAP_KIND) \
+ LINEMAPS_MAP_AT (SET, MAP_KIND, LINEMAPS_ALLOCATED (SET, MAP_KIND) - 1)
+
+/* Returns a pointer to the memory region where ordinary maps are
+ allocated in the line table SET. */
+#define LINEMAPS_ORDINARY_MAPS(SET) \
+ LINEMAPS_MAPS (SET, false)
+
+/* Returns the INDEXth ordinary map. */
+#define LINEMAPS_ORDINARY_MAP_AT(SET, INDEX) \
+ LINEMAPS_MAP_AT (SET, false, INDEX)
+
+/* Return the number of ordinary maps allocated in the line table
+ SET. */
+#define LINEMAPS_ORDINARY_ALLOCATED(SET) \
+ LINEMAPS_ALLOCATED(SET, false)
+
+/* Return the number of ordinary maps used in the line table SET. */
+#define LINEMAPS_ORDINARY_USED(SET) \
+ LINEMAPS_USED(SET, false)
+
+/* Return the index of the last ordinary map that was looked up with
+ linemap_lookup. */
+#define LINEMAPS_ORDINARY_CACHE(SET) \
+ LINEMAPS_CACHE(SET, false)
+
+/* Returns a pointer to the last ordinary map used in the line table
+ SET. */
+#define LINEMAPS_LAST_ORDINARY_MAP(SET) \
+ LINEMAPS_LAST_MAP(SET, false)
+
+/* Returns a pointer to the last ordinary map allocated the line table
+ SET. */
+#define LINEMAPS_LAST_ALLOCATED_ORDINARY_MAP(SET) \
+ LINEMAPS_LAST_ALLOCATED_MAP(SET, false)
+
+/* Returns a pointer to the begining of the region where macro maps
+ are allcoated. */
+#define LINEMAPS_MACRO_MAPS(SET) \
+ LINEMAPS_MAPS(SET, true)
+
+/* Returns the INDEXth macro map. */
+#define LINEMAPS_MACRO_MAP_AT(SET, INDEX) \
+ LINEMAPS_MAP_AT (SET, true, INDEX)
+
+/* Returns the number of macro maps that were allocated in the line
+ table SET. */
+#define LINEMAPS_MACRO_ALLOCATED(SET) \
+ LINEMAPS_ALLOCATED(SET, true)
+
+/* Returns the number of macro maps used in the line table SET. */
+#define LINEMAPS_MACRO_USED(SET) \
+ LINEMAPS_USED(SET, true)
+
+/* Returns the index of the last macro map looked up with
+ linemap_lookup. */
+#define LINEMAPS_MACRO_CACHE(SET) \
+ LINEMAPS_CACHE(SET, true)
+
+/* Returns the lowest location [of a token resulting from macro
+ expansion] encoded in this line table. */
+#define LINEMAPS_MACRO_LOWEST_LOCATION(SET) \
+ (LINEMAPS_MACRO_USED (set) \
+ ? MAP_START_LOCATION (LINEMAPS_LAST_MACRO_MAP (set)) \
+ : MAX_SOURCE_LOCATION)
+
+/* Returns the last macro map used in the line table SET. */
+#define LINEMAPS_LAST_MACRO_MAP(SET) \
+ LINEMAPS_LAST_MAP (SET, true)
+
+/* Returns the last macro map allocated in the line table SET. */
+#define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
+ LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
+
/* Initialize a line map set. */
extern void linemap_init (struct line_maps *);
-/* Free a line map set. */
-extern void linemap_free (struct line_maps *);
-
/* Check for and warn about line_maps entered but not exited. */
extern void linemap_check_files_exited (struct line_maps *);
@@ -117,10 +425,12 @@ extern source_location linemap_line_start
(struct line_maps *set, linenum_type to_line, unsigned int max_column_hint);
/* Add a mapping of logical source line to physical source file and
- line number.
+ line number. This function creates an "ordinary map", which is a
+ map that records locations of tokens that are not part of macro
+ replacement-lists present at a macro expansion point.
The text pointed to by TO_FILE must have a lifetime
- at least as long as the final call to lookup_line (). An empty
+ at least as long as the lifetime of SET. An empty
TO_FILE means standard input. If reason is LC_LEAVE, and
TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
natural values considering the file we are returning to.
@@ -131,41 +441,271 @@ extern const struct line_map *linemap_add
(struct line_maps *, enum lc_reason, unsigned int sysp,
const char *to_file, linenum_type to_line);
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. */
+/* Given a logical source location, returns the map which the
+ corresponding (source file, line, column) triplet can be deduced
+ from. Since the set is built chronologically, the logical lines are
+ monotonic increasing, and so the list is sorted and we can use a
+ binary search. If no line map have been allocated yet, this
+ function returns NULL. */
extern const struct line_map *linemap_lookup
(struct line_maps *, source_location);
+/* Returns TRUE if the line table set tracks token locations accross
+ macro expansion, FALSE otherwise. */
+bool linemap_tracks_macro_expansion_locs_p (struct line_maps *);
+
+/* Return TRUE if MAP encodes locations coming from a macro
+ replacement-list at macro expansion point. */
+bool linemap_macro_expansion_map_p (const struct line_map *);
+
+/* Return the name of the macro associated to MACRO_MAP. */
+const char* linemap_map_get_macro_name (const struct line_map*);
+
+/* Return a positive value if LOCATION is the locus of a token that is
+ located in a system header, O otherwise. It returns 1 if LOCATION
+ is the locus of a token that is located in a system header, and 2
+ if LOCATION is the locus of a token located in a C system header
+ that therefore needs to be extern "C" protected in C++.
+
+ Note that this function returns 1 if LOCATION belongs to a token
+ that is part of a macro replacement-list defined in a system
+ header, but expanded in a non-system file. */
+int linemap_location_in_system_header_p (struct line_maps *,
+ source_location);
+
+/* Return TRUE if LOCATION is a source code location of a token coming
+ from a macro replacement-list at a macro expansion point, FALSE
+ otherwise. */
+bool linemap_location_from_macro_expansion_p (struct line_maps *,
+ source_location);
+
/* source_location values from 0 to RESERVED_LOCATION_COUNT-1 will
be reserved for libcpp user as special values, no token from libcpp
will contain any of those locations. */
#define RESERVED_LOCATION_COUNT 2
/* Converts a map and a source_location to source line. */
-#define SOURCE_LINE(MAP, LOC) \
- ((((LOC) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line)
-
-#define SOURCE_COLUMN(MAP, LOC) \
- (((LOC) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1))
-
-/* Returns the last source line within a map. This is the (last) line
- of the #include, or other directive, that caused a map change. */
+#define SOURCE_LINE(MAP, LOC) \
+ (((((LOC) - linemap_check_ordinary (MAP)->start_location) \
+ >> (MAP)->d.ordinary.column_bits) + (MAP)->d.ordinary.to_line))
+
+/* Convert a map and source_location to source column number. */
+#define SOURCE_COLUMN(MAP, LOC) \
+ ((((LOC) - linemap_check_ordinary (MAP)->start_location) \
+ & ((1 << (MAP)->d.ordinary.column_bits) - 1)))
+
+/* Returns the last source line number within an ordinary map. This
+ is the (last) line of the #include, or other directive, that caused
+ a map change. */
#define LAST_SOURCE_LINE(MAP) \
SOURCE_LINE (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
+
+/* Return the last column number within an ordinary map. */
#define LAST_SOURCE_COLUMN(MAP) \
SOURCE_COLUMN (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
-#define LAST_SOURCE_LINE_LOCATION(MAP) \
- ((((MAP)[1].start_location - 1 - (MAP)->start_location) \
- & ~((1 << (MAP)->column_bits) - 1)) \
- + (MAP)->start_location)
-/* Returns the map a given map was included from. */
-#define INCLUDED_FROM(SET, MAP) (&(SET)->maps[(MAP)->included_from])
+/* Return the location of the last source line within an ordinary
+ map. */
+#define LAST_SOURCE_LINE_LOCATION(MAP) \
+ ((((linemap_check_ordinary (MAP)[1].start_location - 1 \
+ - (MAP)->start_location) \
+ & ~((1 << (MAP)->d.ordinary.column_bits) - 1)) \
+ + (MAP)->start_location))
+
+/* Returns the map a given map was included from, or NULL if the map
+ belongs to the main file, i.e, a file that wasn't included by
+ another one. */
+#define INCLUDED_FROM(SET, MAP) \
+ ((linemap_check_ordinary (MAP)->d.ordinary.included_from == -1) \
+ ? NULL \
+ : (&LINEMAPS_ORDINARY_MAPS (SET)[(MAP)->d.ordinary.included_from]))
/* Nonzero if the map is at the bottom of the include stack. */
-#define MAIN_FILE_P(MAP) ((MAP)->included_from < 0)
+#define MAIN_FILE_P(MAP) \
+ ((linemap_check_ordinary (MAP)->d.ordinary.included_from < 0))
+
+#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Assertion macro to be used in line-map code. */
+#define linemap_assert(EXPR) \
+ do { \
+ if (! (EXPR)) \
+ abort (); \
+ } while (0)
+
+/* Assert that MAP encodes locations of tokens that are not part of
+ the replacement-list of a macro expansion. */
+#define linemap_check_ordinary(LINE_MAP) __extension__ \
+ ({linemap_assert (!linemap_macro_expansion_map_p (LINE_MAP)); \
+ (LINE_MAP);})
+#else
+#define linemap_assert(EXPR)
+#define linemap_check_ordinary(LINE_MAP) (LINE_MAP)
+#endif
+/* Encode and return a source_location from a column number. The
+ source line considered is the last source line used to call
+ linemap_line_start, i.e, the last source line which a location was
+ encoded from. */
extern source_location
-linemap_position_for_column (struct line_maps *set, unsigned int to_column);
+linemap_position_for_column (struct line_maps *, unsigned int);
+
+/* Encode and return a source location from a given line and
+ column. */
+source_location linemap_position_for_line_and_column (struct line_map *,
+ linenum_type,
+ unsigned int);
+/* Return the file this map is for. */
+#define LINEMAP_FILE(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.to_file)
+
+/* Return the line number this map started encoding location from. */
+#define LINEMAP_LINE(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.to_line)
+
+/* Return a positive value if map encodes locations from a system
+ header, 0 otherwise. Returns 1 if MAP encodes locations in a
+ system header and 2 if it encodes locations in a C system header
+ that therefore needs to be extern "C" protected in C++. */
+#define LINEMAP_SYSP(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.sysp)
+
+/* Return a positive value if PRE denotes the location of a token that
+ comes before the token of POST, 0 if PRE denotes the location of
+ the same token as the token for POST, and a negative value
+ otherwise. */
+int linemap_compare_locations (struct line_maps *set,
+ source_location pre,
+ source_location post);
+
+/* Return TRUE if LOC_A denotes the location a token that comes
+ topogically before the token denoted by location LOC_B, or if they
+ are equal. */
+#define linemap_location_before_p(SET, LOC_A, LOC_B) \
+ (linemap_compare_locations ((SET), (LOC_A), (LOC_B)) >= 0)
+
+typedef struct
+{
+ /* The name of the source file involved. */
+ const char *file;
+
+ /* The line-location in the source file. */
+ int line;
+
+ int column;
+
+ /* In a system header?. */
+ bool sysp;
+} expanded_location;
+
+/* This is enum is used by the function linemap_resolve_location
+ below. The meaning of the values is explained in the comment of
+ that function. */
+enum location_resolution_kind
+{
+ LRK_MACRO_EXPANSION_POINT,
+ LRK_SPELLING_LOCATION,
+ LRK_MACRO_DEFINITION_LOCATION
+};
+
+/* Resolve a virtual location into either a spelling location, an
+ expansion point location or a token argument replacement point
+ location. Return the map that encodes the virtual location as well
+ as the resolved location.
+
+ If LOC is *NOT* the location of a token resulting from the
+ expansion of a macro, then the parameter LRK (which stands for
+ Location Resolution Kind) is ignored and the resulting location
+ just equals the one given in argument.
+
+ Now if LOC *IS* the location of a token resulting from the
+ expansion of a macro, this is what happens.
+
+ * If LRK is set to LRK_MACRO_EXPANSION_POINT
+ -------------------------------
+
+ The virtual location is resolved to the first macro expansion point
+ that led to this macro expansion.
+
+ * If LRK is set to LRK_SPELLING_LOCATION
+ -------------------------------------
+
+ The virtual location is resolved to the locus where the token has
+ been spelled in the source. This can follow through all the macro
+ expansions that led to the token.
+
+ * If LRK is set to LRK_MACRO_DEFINITION_LOCATION
+ --------------------------------------
+
+ The virtual location is resolved to the locus of the token in the
+ context of the macro definition.
+
+ If LOC is the locus of a token that is an argument of a
+ function-like macro [replacing a parameter in the replacement list
+ of the macro] the virtual location is resolved to the locus of the
+ parameter that is replaced, in the context of the definition of the
+ macro.
+
+ If LOC is the locus of a token that is not an argument of a
+ function-like macro, then the function behaves as if LRK was set to
+ LRK_SPELLING_LOCATION.
+
+ If LOC_MAP is not NULL, *LOC_MAP is set to the map encoding the
+ returned location. */
+
+source_location linemap_resolve_location (struct line_maps *,
+ source_location loc,
+ enum location_resolution_kind lrk,
+ const struct line_map **loc_map);
+
+/* Suppose that LOC is the virtual location of a token coming from the
+ expansion of a macro M. This function then steps up to get the
+ location L of the point where M got expanded. If L is a spelling
+ location inside a macro expansion M', then this function returns
+ the point where M' was expanded. LOC_MAP is an output parameter.
+ When non-NULL, *LOC_MAP is set the the map of the returned
+ location. */
+source_location linemap_unwind_toward_expansion (struct line_maps *,
+ source_location loc,
+ const struct line_map **loc_map);
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC must be a spelling (non-virtual) location. */
+
+expanded_location linemap_expand_location (const struct line_map *,
+ source_location loc);
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC can be a virtual location. The LRK parameter
+ is the same as for linemap_resolve_location. */
+
+expanded_location linemap_expand_location_full (struct line_maps *,
+ source_location loc,
+ enum location_resolution_kind lrk);
+
+/* Statistics about maps allocation and usage as returned by
+ linemap_get_statistics. */
+struct linemap_stats
+{
+ long num_ordinary_maps_allocated;
+ long num_ordinary_maps_used;
+ long ordinary_maps_allocated_size;
+ long ordinary_maps_used_size;
+ long num_expanded_macros;
+ long num_macro_tokens;
+ long num_macro_maps_used;
+ long macro_maps_allocated_size;
+ long macro_maps_used_size;
+ long macro_maps_locations_size;
+ long duplicated_macro_maps_locations_size;
+};
+
+/* Compute and return statistics about the memory consumption of some
+ parts of the line table SET. */
+void linemap_get_statistics (struct line_maps *, struct linemap_stats *);
+
+/* Dump debugging information about source location LOC into the file
+ stream STREAM. SET is the line map set LOC comes from. */
+void linemap_dump_location (struct line_maps *, source_location, FILE *);
#endif /* !LIBCPP_LINE_MAP_H */
diff --git a/libcpp/init.c b/libcpp/init.c
index c5c53256d35..6771e638970 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -154,6 +154,7 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
init_library ();
pfile = XCNEW (cpp_reader);
+ memset (&pfile->base_context, 0, sizeof (pfile->base_context));
cpp_set_lang (pfile, lang);
CPP_OPTION (pfile, warn_multichar) = 1;
@@ -213,7 +214,7 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
/* Initialize the base context. */
pfile->context = &pfile->base_context;
- pfile->base_context.macro = 0;
+ pfile->base_context.c.macro = 0;
pfile->base_context.prev = pfile->base_context.next = 0;
/* Aligned and unaligned storage. */
@@ -586,7 +587,9 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname)
if (CPP_OPTION (pfile, preprocessed))
{
read_original_filename (pfile);
- fname = pfile->line_table->maps[pfile->line_table->used-1].to_file;
+ fname =
+ ORDINARY_MAP_FILE_NAME
+ ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table)));
}
return fname;
}
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 6c423f056bc..6fb2606c9b8 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -1,6 +1,6 @@
/* Part of CPP library.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
- 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -67,7 +67,8 @@ struct cset_converter
#define CPP_INCREMENT_LINE(PFILE, COLS_HINT) do { \
const struct line_maps *line_table = PFILE->line_table; \
- const struct line_map *map = &line_table->maps[line_table->used-1]; \
+ const struct line_map *map = \
+ LINEMAPS_LAST_ORDINARY_MAP (line_table); \
linenum_type line = SOURCE_LINE (map, line_table->highest_line); \
linemap_line_start (PFILE->line_table, line + 1, COLS_HINT); \
} while (0)
@@ -138,6 +139,40 @@ struct tokenrun
#define CUR(c) ((c)->u.trad.cur)
#define RLIMIT(c) ((c)->u.trad.rlimit)
+/* This describes some additional data that is added to the macro
+ token context of type cpp_context, when -ftrack-macro-expansion is
+ on. */
+typedef struct
+{
+ /* The node of the macro we are referring to. */
+ cpp_hashnode *macro_node;
+ /* This buffer contains an array of virtual locations. The virtual
+ location at index 0 is the virtual location of the token at index
+ 0 in the current instance of cpp_context; similarly for all the
+ other virtual locations. */
+ source_location *virt_locs;
+ /* This is a pointer to the current virtual location. This is used
+ to iterate over the virtual locations while we iterate over the
+ tokens they belong to. */
+ source_location *cur_virt_loc;
+} macro_context;
+
+/* The kind of tokens carried by a cpp_context. */
+enum context_tokens_kind {
+ /* This is the value of cpp_context::tokens_kind if u.iso.first
+ contains an instance of cpp_token **. */
+ TOKENS_KIND_INDIRECT,
+ /* This is the value of cpp_context::tokens_kind if u.iso.first
+ contains an instance of cpp_token *. */
+ TOKENS_KIND_DIRECT,
+ /* This is the value of cpp_context::tokens_kind when the token
+ context contains tokens resulting from macro expansion. In that
+ case struct cpp_context::macro points to an instance of struct
+ macro_context. This is used only when the
+ -ftrack-macro-expansion flag is on. */
+ TOKENS_KIND_EXTENDED
+};
+
typedef struct cpp_context cpp_context;
struct cpp_context
{
@@ -167,11 +202,24 @@ struct cpp_context
When the context is popped, the buffer is released. */
_cpp_buff *buff;
- /* For a macro context, the macro node, otherwise NULL. */
- cpp_hashnode *macro;
+ /* If tokens_kind is TOKEN_KIND_EXTENDED, then (as we thus are in a
+ macro context) this is a pointer to an instance of macro_context.
+ Otherwise if tokens_kind is *not* TOKEN_KIND_EXTENDED, then, if
+ we are in a macro context, this is a pointer to an instance of
+ cpp_hashnode, representing the name of the macro this context is
+ for. If we are not in a macro context, then this is just NULL.
+ Note that when tokens_kind is TOKEN_KIND_EXTENDED, the memory
+ used by the instance of macro_context pointed to by this member
+ is de-allocated upon de-allocation of the instance of struct
+ cpp_context. */
+ union
+ {
+ macro_context *mc;
+ cpp_hashnode *macro;
+ } c;
- /* True if utoken element is token, else ptoken. */
- bool direct_p;
+ /* This determines the type of tokens held by this context. */
+ enum context_tokens_kind tokens_kind;
};
struct lexer_state
@@ -604,6 +652,7 @@ extern cpp_token *_cpp_lex_direct (cpp_reader *);
extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *);
+extern int _cpp_remaining_tokens_num_in_context (cpp_reader *);
/* In init.c. */
extern void _cpp_maybe_push_include_file (cpp_reader *);
@@ -739,6 +788,76 @@ ufputs (const unsigned char *s, FILE *f)
return fputs ((const char *)s, f);
}
+ /* In line-map.c. */
+
+/* Create a macro map. A macro map encodes source locations of tokens
+ that are part of a macro replacement-list, at a macro expansion
+ point. See the extensive comments of struct line_map and struct
+ line_map_macro, in line-map.h.
+
+ This map shall be created when the macro is expanded. The map
+ encodes the source location of the expansion point of the macro as
+ well as the "original" source location of each token that is part
+ of the macro replacement-list. If a macro is defined but never
+ expanded, it has no macro map. SET is the set of maps the macro
+ map should be part of. MACRO_NODE is the macro which the new macro
+ map should encode source locations for. EXPANSION is the location
+ of the expansion point of MACRO. For function-like macros
+ invocations, it's best to make it point to the closing parenthesis
+ of the macro, rather than the the location of the first character
+ of the macro. NUM_TOKENS is the number of tokens that are part of
+ the replacement-list of MACRO. */
+const struct line_map *linemap_enter_macro (struct line_maps *,
+ struct cpp_hashnode*,
+ source_location,
+ unsigned int);
+
+/* Create and return a virtual location for a token that is part of a
+ macro expansion-list at a macro expansion point. See the comment
+ inside struct line_map_macro to see what an expansion-list exactly
+ is.
+
+ A call to this function must come after a call to
+ linemap_enter_macro.
+
+ MAP is the map into which the source location is created. TOKEN_NO
+ is the index of the token in the macro replacement-list, starting
+ at number 0.
+
+ ORIG_LOC is the location of the token outside of this macro
+ expansion. If the token comes originally from the macro
+ definition, it is the locus in the macro definition; otherwise it
+ is a location in the context of the caller of this macro expansion
+ (which is a virtual location or a source location if the caller is
+ itself a macro expansion or not).
+
+ MACRO_DEFINITION_LOC is the location in the macro definition,
+ either of the token itself or of a macro parameter that it
+ replaces. */
+source_location linemap_add_macro_token (const struct line_map *,
+ unsigned int,
+ source_location,
+ source_location);
+
+/* Return the source line number corresponding to source location
+ LOCATION. SET is the line map set LOCATION comes from. If
+ LOCATION is the location of token that is part of the
+ expansion-list of a macro expansion return the line number of the
+ macro expansion point. */
+int linemap_get_expansion_line (struct line_maps *,
+ source_location);
+
+/* Return the path of the file corresponding to source code location
+ LOCATION.
+
+ If LOCATION is the location of a token that is part of the
+ replacement-list of a macro expansion return the file path of the
+ macro expansion point.
+
+ SET is the line map set LOCATION comes from. */
+const char* linemap_get_expansion_filename (struct line_maps *,
+ source_location);
+
#ifdef __cplusplus
}
#endif
diff --git a/libcpp/lex.c b/libcpp/lex.c
index 75b2b1dc7ff..cd6ae9f67dd 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -1703,6 +1703,38 @@ next_tokenrun (tokenrun *run)
return run->next;
}
+/* Return the number of not yet processed token in the the current
+ context. */
+int
+_cpp_remaining_tokens_num_in_context (cpp_reader *pfile)
+{
+ cpp_context *context = pfile->context;
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
+ return ((LAST (context).token - FIRST (context).token)
+ / sizeof (cpp_token));
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT
+ || context->tokens_kind == TOKENS_KIND_EXTENDED)
+ return ((LAST (context).ptoken - FIRST (context).ptoken)
+ / sizeof (cpp_token *));
+ else
+ abort ();
+}
+
+/* Returns the token present at index INDEX in the current context.
+ If INDEX is zero, the next token to be processed is returned. */
+static const cpp_token*
+_cpp_token_from_context_at (cpp_reader *pfile, int index)
+{
+ cpp_context *context = pfile->context;
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
+ return &(FIRST (context).token[index]);
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT
+ || context->tokens_kind == TOKENS_KIND_EXTENDED)
+ return FIRST (context).ptoken[index];
+ else
+ abort ();
+}
+
/* Look ahead in the input stream. */
const cpp_token *
cpp_peek_token (cpp_reader *pfile, int index)
@@ -1714,15 +1746,10 @@ cpp_peek_token (cpp_reader *pfile, int index)
/* First, scan through any pending cpp_context objects. */
while (context->prev)
{
- ptrdiff_t sz = (context->direct_p
- ? LAST (context).token - FIRST (context).token
- : LAST (context).ptoken - FIRST (context).ptoken);
+ ptrdiff_t sz = _cpp_remaining_tokens_num_in_context (pfile);
if (index < (int) sz)
- return (context->direct_p
- ? FIRST (context).token + index
- : *(FIRST (context).ptoken + index));
-
+ return _cpp_token_from_context_at (pfile, index);
index -= (int) sz;
context = context->prev;
}
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 2a0749aad2e..fb3be3a5f60 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1,5 +1,5 @@
/* Map logical line numbers to (source file, line number) pairs.
- Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009
+ Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -23,24 +23,41 @@ along with this program; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "line-map.h"
+#include "cpplib.h"
+#include "internal.h"
static void trace_include (const struct line_maps *, const struct line_map *);
+static const struct line_map * linemap_ordinary_map_lookup (struct line_maps *,
+ source_location);
+static const struct line_map* linemap_macro_map_lookup (struct line_maps *,
+ source_location);
+static source_location linemap_macro_map_loc_to_def_point
+(const struct line_map*, source_location);
+static source_location linemap_macro_map_loc_unwind_toward_spelling
+(const struct line_map*, source_location);
+static source_location linemap_macro_map_loc_to_exp_point
+(const struct line_map*, source_location);
+static source_location linemap_macro_loc_to_spelling_point
+(struct line_maps *, source_location, const struct line_map **);
+static source_location linemap_macro_loc_to_def_point (struct line_maps *,
+ source_location,
+ const struct line_map **);
+static source_location linemap_macro_loc_to_exp_point (struct line_maps *,
+ source_location,
+ const struct line_map **);
+
+/* Counters defined in macro.c. */
+extern unsigned num_expanded_macros_counter;
+extern unsigned num_macro_tokens_counter;
/* Initialize a line map set. */
void
linemap_init (struct line_maps *set)
{
- set->maps = NULL;
- set->allocated = 0;
- set->used = 0;
- set->trace_includes = false;
- set->depth = 0;
- set->cache = 0;
+ memset (set, 0, sizeof (struct line_maps));
set->highest_location = RESERVED_LOCATION_COUNT - 1;
set->highest_line = RESERVED_LOCATION_COUNT - 1;
- set->max_column_hint = 0;
- set->reallocator = 0;
}
/* Check for and warn about line_maps entered but not exited. */
@@ -51,23 +68,82 @@ linemap_check_files_exited (struct line_maps *set)
struct line_map *map;
/* Depending upon whether we are handling preprocessed input or
not, this can be a user error or an ICE. */
- for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
+ for (map = LINEMAPS_LAST_ORDINARY_MAP (set);
+ ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))
fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
- map->to_file);
+ ORDINARY_MAP_FILE_NAME (map));
}
-
-/* Free a line map set. */
-void
-linemap_free (struct line_maps *set)
+/* Create a new line map in the line map set SET, and return it.
+ REASON is the reason of creating the map. It determines the type
+ of map created (ordinary or macro map). Note that ordinary maps and
+ macro maps are allocated in different memory location. */
+
+static struct line_map *
+new_linemap (struct line_maps *set,
+ enum lc_reason reason)
{
- if (set->maps)
+ /* Depending on this variable, a macro map would be allocated in a
+ different memory location than an ordinary map. */
+ bool macro_map_p = (reason == LC_ENTER_MACRO);
+ struct line_map *result;
+
+ if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
{
- linemap_check_files_exited (set);
+ /* We ran out of allocated line maps. Let's allocate more. */
+ unsigned alloc_size;
+
+ line_map_realloc reallocator
+ = set->reallocator ? set->reallocator : xrealloc;
+ line_map_round_alloc_size_func round_alloc_size =
+ set->round_alloc_size;
+
+ /* We are going to execute some dance to try to reduce the
+ overhead of the memory allocator, in case we are using the
+ ggc-page.c one.
+
+ The actual size of memory we are going to get back from the
+ allocator is the smallest power of 2 that is greater than the
+ size we requested. So let's consider that size then. */
+
+ alloc_size =
+ (2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256)
+ * sizeof (struct line_map);
- free (set->maps);
+ /* Get the actual size of memory that is going to be allocated
+ by the allocator. */
+ alloc_size = round_alloc_size (alloc_size);
+
+ /* Now alloc_size contains the exact memory size we would get if
+ we have asked for the initial alloc_size amount of memory.
+ Let's get back to the number of macro map that amounts
+ to. */
+ LINEMAPS_ALLOCATED (set, macro_map_p) =
+ alloc_size / (sizeof (struct line_map));
+
+ /* And now let's really do the re-allocation. */
+ LINEMAPS_MAPS (set, macro_map_p) =
+ (struct line_map *) (*reallocator)
+ (LINEMAPS_MAPS (set, macro_map_p),
+ (LINEMAPS_ALLOCATED (set, macro_map_p)
+ * sizeof (struct line_map)));
+
+ result =
+ &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
+ memset (result, 0,
+ ((LINEMAPS_ALLOCATED (set, macro_map_p)
+ - LINEMAPS_USED (set, macro_map_p))
+ * sizeof (struct line_map)));
}
+ else
+ result =
+ &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
+
+ LINEMAPS_USED (set, macro_map_p)++;
+
+ result->reason = reason;
+ return result;
}
/* Add a mapping of logical source line to physical source file and
@@ -90,23 +166,24 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
struct line_map *map;
source_location start_location = set->highest_location + 1;
- if (set->used && start_location < set->maps[set->used - 1].start_location)
- abort ();
+ linemap_assert (!(LINEMAPS_ORDINARY_USED (set)
+ && (start_location
+ < MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set)))));
+
+ /* When we enter the file for the first time reason cannot be
+ LC_RENAME. */
+ linemap_assert (!(set->depth == 0 && reason == LC_RENAME));
- if (set->used == set->allocated)
+ /* If we are leaving the main file, return a NULL map. */
+ if (reason == LC_LEAVE
+ && MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set))
+ && to_file == NULL)
{
- line_map_realloc reallocator
- = set->reallocator ? set->reallocator : xrealloc;
- set->allocated = 2 * set->allocated + 256;
- set->maps
- = (struct line_map *) (*reallocator) (set->maps,
- set->allocated
- * sizeof (struct line_map));
- memset (&set->maps[set->used], 0, ((set->allocated - set->used)
- * sizeof (struct line_map)));
+ set->depth--;
+ return NULL;
}
- map = &set->maps[set->used];
+ map = new_linemap (set, reason);
if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
to_file = "<stdin>";
@@ -114,29 +191,35 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
if (reason == LC_RENAME_VERBATIM)
reason = LC_RENAME;
- if (set->depth == 0 && reason == LC_RENAME)
- abort ();
-
if (reason == LC_LEAVE)
{
+ /* When we are just leaving an "included" file, and jump to the next
+ location inside the "includer" right after the #include
+ "included", this variable points the map in use right before the
+ #include "included", inside the same "includer" file. */
struct line_map *from;
bool error;
if (MAIN_FILE_P (map - 1))
{
- if (to_file == NULL)
- {
- set->depth--;
- return NULL;
- }
+ /* So this _should_ means we are leaving the main file --
+ effectively ending the compilation unit. But to_file not
+ being NULL means the caller thinks we are leaving to
+ another file. This is an erroneous behaviour but we'll
+ try to recover from it. Let's pretend we are not leaving
+ the main file. */
error = true;
reason = LC_RENAME;
from = map - 1;
}
else
{
+ /* (MAP - 1) points to the map we are leaving. The
+ map from which (MAP - 1) got included should be the map
+ that comes right before MAP in the same file. */
from = INCLUDED_FROM (set, map - 1);
- error = to_file && filename_cmp (from->to_file, to_file);
+ error = to_file && filename_cmp (ORDINARY_MAP_FILE_NAME (from),
+ to_file);
}
/* Depending upon whether we are handling preprocessed input or
@@ -148,55 +231,176 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
/* A TO_FILE of NULL is special - we use the natural values. */
if (error || to_file == NULL)
{
- to_file = from->to_file;
+ to_file = ORDINARY_MAP_FILE_NAME (from);
to_line = SOURCE_LINE (from, from[1].start_location);
- sysp = from->sysp;
+ sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
}
}
- map->reason = reason;
- map->sysp = sysp;
- map->start_location = start_location;
- map->to_file = to_file;
- map->to_line = to_line;
- set->cache = set->used++;
- map->column_bits = 0;
+ linemap_assert (reason != LC_ENTER_MACRO);
+ ORDINARY_MAP_IN_SYSTEM_HEADER_P (map) = sysp;
+ MAP_START_LOCATION (map) = start_location;
+ ORDINARY_MAP_FILE_NAME (map) = to_file;
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map) = to_line;
+ LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
+ ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = 0;
set->highest_location = start_location;
set->highest_line = start_location;
set->max_column_hint = 0;
if (reason == LC_ENTER)
{
- map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2);
set->depth++;
if (set->trace_includes)
trace_include (set, map);
}
else if (reason == LC_RENAME)
- map->included_from = map[-1].included_from;
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]);
else if (reason == LC_LEAVE)
{
set->depth--;
- map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1));
}
return map;
}
+/* Returns TRUE if the line table set tracks token locations accross
+ macro expansion, FALSE otherwise. */
+
+bool
+linemap_tracks_macro_expansion_locs_p (struct line_maps *set)
+{
+ return LINEMAPS_MACRO_MAPS (set) != NULL;
+}
+
+/* Create a macro map. A macro map encodes source locations of tokens
+ that are part of a macro replacement-list, at a macro expansion
+ point. See the extensive comments of struct line_map and struct
+ line_map_macro, in line-map.h.
+
+ This map shall be created when the macro is expanded. The map
+ encodes the source location of the expansion point of the macro as
+ well as the "original" source location of each token that is part
+ of the macro replacement-list. If a macro is defined but never
+ expanded, it has no macro map. SET is the set of maps the macro
+ map should be part of. MACRO_NODE is the macro which the new macro
+ map should encode source locations for. EXPANSION is the location
+ of the expansion point of MACRO. For function-like macros
+ invocations, it's best to make it point to the closing parenthesis
+ of the macro, rather than the the location of the first character
+ of the macro. NUM_TOKENS is the number of tokens that are part of
+ the replacement-list of MACRO.
+
+ Note that when we run out of the integer space available for source
+ locations, this function returns NULL. In that case, callers of
+ this function cannot encode {line,column} pairs into locations of
+ macro tokens anymore. */
+
+const struct line_map *
+linemap_enter_macro (struct line_maps *set, struct cpp_hashnode *macro_node,
+ source_location expansion, unsigned int num_tokens)
+{
+ struct line_map *map;
+ source_location start_location;
+ line_map_realloc reallocator
+ = set->reallocator ? set->reallocator : xrealloc;
+
+ start_location = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
+
+ if (start_location <= set->highest_line
+ || start_location > LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ /* We ran out of macro map space. */
+ return NULL;
+
+ map = new_linemap (set, LC_ENTER_MACRO);
+
+ MAP_START_LOCATION (map) = start_location;
+ MACRO_MAP_MACRO (map) = macro_node;
+ MACRO_MAP_NUM_MACRO_TOKENS (map) = num_tokens;
+ MACRO_MAP_LOCATIONS (map)
+ = (source_location*) reallocator (NULL,
+ 2 * num_tokens
+ * sizeof (source_location));
+ MACRO_MAP_EXPANSION_POINT_LOCATION (map) = expansion;
+ memset (MACRO_MAP_LOCATIONS (map), 0,
+ num_tokens * sizeof (source_location));
+
+ LINEMAPS_MACRO_CACHE (set) = LINEMAPS_MACRO_USED (set) - 1;
+ set->max_column_hint = 0;
+
+ return map;
+}
+
+/* Create and return a virtual location for a token that is part of a
+ macro expansion-list at a macro expansion point. See the comment
+ inside struct line_map_macro to see what an expansion-list exactly
+ is.
+
+ A call to this function must come after a call to
+ linemap_enter_macro.
+
+ MAP is the map into which the source location is created. TOKEN_NO
+ is the index of the token in the macro replacement-list, starting
+ at number 0.
+
+ ORIG_LOC is the location of the token outside of this macro
+ expansion. If the token comes originally from the macro
+ definition, it is the locus in the macro definition; otherwise it
+ is a location in the context of the caller of this macro expansion
+ (which is a virtual location or a source location if the caller is
+ itself a macro expansion or not).
+
+ MACRO_DEFINITION_LOC is the location in the macro definition,
+ either of the token itself or of a macro parameter that it
+ replaces. */
+
+source_location
+linemap_add_macro_token (const struct line_map *map,
+ unsigned int token_no,
+ source_location orig_loc,
+ source_location orig_parm_replacement_loc)
+{
+ source_location result;
+
+ linemap_assert (linemap_macro_expansion_map_p (map));
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ MACRO_MAP_LOCATIONS (map)[2 * token_no] = orig_loc;
+ MACRO_MAP_LOCATIONS (map)[2 * token_no + 1] = orig_parm_replacement_loc;
+
+ result = MAP_START_LOCATION (map) + token_no;
+ return result;
+}
+
+/* Return a source_location for the start (i.e. column==0) of
+ (physical) line TO_LINE in the current source file (as in the
+ most recent linemap_add). MAX_COLUMN_HINT is the highest column
+ number we expect to use in this line (but it does not change
+ the highest_location). */
+
source_location
linemap_line_start (struct line_maps *set, linenum_type to_line,
unsigned int max_column_hint)
{
- struct line_map *map = &set->maps[set->used - 1];
+ struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
source_location highest = set->highest_location;
source_location r;
- linenum_type last_line = SOURCE_LINE (map, set->highest_line);
+ linenum_type last_line =
+ SOURCE_LINE (map, set->highest_line);
int line_delta = to_line - last_line;
bool add_map = false;
+
if (line_delta < 0
- || (line_delta > 10 && line_delta * map->column_bits > 1000)
- || (max_column_hint >= (1U << map->column_bits))
- || (max_column_hint <= 80 && map->column_bits >= 10))
+ || (line_delta > 10
+ && line_delta * ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) > 1000)
+ || (max_column_hint >= (1U << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)))
+ || (max_column_hint <= 80
+ && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10))
{
add_map = true;
}
@@ -224,16 +428,27 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
/* Allocate the new line_map. However, if the current map only has a
single line we can sometimes just increase its column_bits instead. */
if (line_delta < 0
- || last_line != map->to_line
+ || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
|| SOURCE_COLUMN (map, highest) >= (1U << column_bits))
- map = (struct line_map *) linemap_add (set, LC_RENAME, map->sysp,
- map->to_file, to_line);
- map->column_bits = column_bits;
- r = map->start_location + ((to_line - map->to_line) << column_bits);
+ map = (struct line_map *) linemap_add (set, LC_RENAME,
+ ORDINARY_MAP_IN_SYSTEM_HEADER_P
+ (map),
+ ORDINARY_MAP_FILE_NAME (map),
+ to_line);
+ ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = column_bits;
+ r = (MAP_START_LOCATION (map)
+ + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
+ << column_bits));
}
else
r = highest - SOURCE_COLUMN (map, highest)
- + (line_delta << map->column_bits);
+ + (line_delta << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
+
+ /* Locations of ordinary tokens are always lower than locations of
+ macro tokens. */
+ if (r >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ return 0;
+
set->highest_line = r;
if (r > set->highest_location)
set->highest_location = r;
@@ -241,10 +456,19 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
return r;
}
+/* Encode and return a source_location from a column number. The
+ source line considered is the last source line used to call
+ linemap_line_start, i.e, the last source line which a location was
+ encoded from. */
+
source_location
linemap_position_for_column (struct line_maps *set, unsigned int to_column)
{
source_location r = set->highest_line;
+
+ linemap_assert
+ (!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
+
if (to_column >= set->max_column_hint)
{
if (r >= 0xC000000 || to_column > 100000)
@@ -254,7 +478,7 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column)
}
else
{
- struct line_map *map = &set->maps[set->used - 1];
+ struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
}
}
@@ -264,25 +488,55 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column)
return r;
}
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. Since the set is built
- chronologically, the logical lines are monotonic increasing, and so
- the list is sorted and we can use a binary search. */
+/* Encode and return a source location from a given line and
+ column. */
-const struct line_map *
+source_location
+linemap_position_for_line_and_column (struct line_map *map,
+ linenum_type line,
+ unsigned column)
+{
+ linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (map) <= line);
+
+ return (MAP_START_LOCATION (map)
+ + ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
+ << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map))
+ + (column & ((1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)) - 1)));
+}
+
+/* Given a virtual source location yielded by a map (either an
+ ordinary or a macro map), returns that map. */
+
+const struct line_map*
linemap_lookup (struct line_maps *set, source_location line)
{
+ if (linemap_location_from_macro_expansion_p (set, line))
+ return linemap_macro_map_lookup (set, line);
+ return linemap_ordinary_map_lookup (set, line);
+}
+
+/* Given a source location yielded by an ordinary map, returns that
+ map. Since the set is built chronologically, the logical lines are
+ monotonic increasing, and so the list is sorted and we can use a
+ binary search. */
+
+static const struct line_map *
+linemap_ordinary_map_lookup (struct line_maps *set, source_location line)
+{
unsigned int md, mn, mx;
- const struct line_map *cached;
+ const struct line_map *cached, *result;
+
+ if (set == NULL || line < RESERVED_LOCATION_COUNT)
+ return NULL;
- mn = set->cache;
- mx = set->used;
+ mn = LINEMAPS_ORDINARY_CACHE (set);
+ mx = LINEMAPS_ORDINARY_USED (set);
- cached = &set->maps[mn];
+ cached = LINEMAPS_ORDINARY_MAP_AT (set, mn);
/* We should get a segfault if no line_maps have been added yet. */
- if (line >= cached->start_location)
+ if (line >= MAP_START_LOCATION (cached))
{
- if (mn + 1 == mx || line < cached[1].start_location)
+ if (mn + 1 == mx || line < MAP_START_LOCATION (&cached[1]))
return cached;
}
else
@@ -294,14 +548,343 @@ linemap_lookup (struct line_maps *set, source_location line)
while (mx - mn > 1)
{
md = (mn + mx) / 2;
- if (set->maps[md].start_location > line)
+ if (MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (set, md)) > line)
mx = md;
else
mn = md;
}
- set->cache = mn;
- return &set->maps[mn];
+ LINEMAPS_ORDINARY_CACHE (set) = mn;
+ result = LINEMAPS_ORDINARY_MAP_AT (set, mn);
+ linemap_assert (line >= MAP_START_LOCATION (result));
+ return result;
+}
+
+/* Given a source location yielded by a macro map, returns that map.
+ Since the set is built chronologically, the logical lines are
+ monotonic decreasing, and so the list is sorted and we can use a
+ binary search. */
+
+static const struct line_map*
+linemap_macro_map_lookup (struct line_maps *set, source_location line)
+{
+ unsigned int md, mn, mx;
+ const struct line_map *cached, *result;
+
+ linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
+
+ if (set == NULL)
+ return NULL;
+
+ mn = LINEMAPS_MACRO_CACHE (set);
+ mx = LINEMAPS_MACRO_USED (set);
+ cached = LINEMAPS_MACRO_MAP_AT (set, mn);
+
+ if (line >= MAP_START_LOCATION (cached))
+ {
+ if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
+ return cached;
+ mx = mn - 1;
+ mn = 0;
+ }
+
+ do
+ {
+ md = (mx + mn) / 2;
+ if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
+ mn = md;
+ else
+ mx = md;
+ } while (mx - mn > 1);
+
+ LINEMAPS_MACRO_CACHE (set) = mx;
+ result = LINEMAPS_MACRO_MAP_AT (set, LINEMAPS_MACRO_CACHE (set));
+ linemap_assert (MAP_START_LOCATION (result) <= line);
+
+ return result;
+}
+
+/* Return TRUE if MAP encodes locations coming from a macro
+ replacement-list at macro expansion point. */
+
+bool
+linemap_macro_expansion_map_p (const struct line_map *map)
+{
+ if (!map)
+ return false;
+ return (map->reason == LC_ENTER_MACRO);
+}
+
+/* If LOCATION is the locus of a token in a replacement-list of a
+ macro expansion return the location of the macro expansion point.
+
+ Read the comments of struct line_map and struct line_map_macro in
+ line-map.h to understand what a macro expansion point is. */
+
+static source_location
+linemap_macro_map_loc_to_exp_point (const struct line_map *map,
+ source_location location ATTRIBUTE_UNUSED)
+{
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+
+ /* Make sure LOCATION is correct. */
+ linemap_assert ((location - MAP_START_LOCATION (map))
+ < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- as part of a macro expansion -- then
+ return the location of the token at the definition point of the
+ macro. Otherwise, return LOCATION. SET is the set of maps
+ location come from. ORIGINAL_MAP is an output parm. If non NULL,
+ the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
+ returned location comes from. */
+
+source_location
+linemap_macro_map_loc_to_def_point (const struct line_map *map,
+ source_location location)
+{
+ unsigned token_no;
+
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+ linemap_assert (location >= RESERVED_LOCATION_COUNT);
+
+ token_no = location - MAP_START_LOCATION (map);
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ location = MACRO_MAP_LOCATIONS (map)[2 * token_no + 1];
+
+ return location;
+}
+
+/* If LOCATION is the locus of a token that is an argument of a
+ function-like macro M and appears in the expansion of M, return the
+ locus of that argument in the context of the caller of M.
+
+ In other words, this returns the xI location presented in the
+ comments of line_map_macro above. */
+source_location
+linemap_macro_map_loc_unwind_toward_spelling (const struct line_map* map,
+ source_location location)
+{
+ unsigned token_no;
+
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+ linemap_assert (location >= RESERVED_LOCATION_COUNT);
+
+ token_no = location - MAP_START_LOCATION (map);
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ location = MACRO_MAP_LOCATIONS (map)[2 * token_no];
+
+ return location;
+}
+
+/* Return the source line number corresponding to source location
+ LOCATION. SET is the line map set LOCATION comes from. If
+ LOCATION is the source location of token that is part of the
+ replacement-list of a macro expansion return the line number of the
+ macro expansion point. */
+
+int
+linemap_get_expansion_line (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return 0;
+
+ location =
+ linemap_macro_loc_to_exp_point (set, location, &map);
+
+ return SOURCE_LINE (map, location);
+}
+
+/* Return the path of the file corresponding to source code location
+ LOCATION.
+
+ If LOCATION is the source location of token that is part of the
+ replacement-list of a macro expansion return the file path of the
+ macro expansion point.
+
+ SET is the line map set LOCATION comes from. */
+
+const char*
+linemap_get_expansion_filename (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return NULL;
+
+ location =
+ linemap_macro_loc_to_exp_point (set, location, &map);
+
+ return LINEMAP_FILE (map);
+}
+
+/* Return the name of the macro associated to MACRO_MAP. */
+
+const char*
+linemap_map_get_macro_name (const struct line_map* macro_map)
+{
+ linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
+ return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
+}
+
+/* Return a positive value if LOCATION is the locus of a token that is
+ located in a system header, O otherwise. It returns 1 if LOCATION
+ is the locus of a token that is located in a system header, and 2
+ if LOCATION is the locus of a token located in a C system header
+ that therefore needs to be extern "C" protected in C++.
+
+ Note that this function returns 1 if LOCATION belongs to a token
+ that is part of a macro replacement-list defined in a system
+ header, but expanded in a non-system file. */
+
+int
+linemap_location_in_system_header_p (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return false;
+
+ location =
+ linemap_resolve_location (set, location, LRK_SPELLING_LOCATION, &map);
+
+ return LINEMAP_SYSP (map);
+}
+
+/* Return TRUE if LOCATION is a source code location of a token coming
+ from a macro replacement-list at a macro expansion point, FALSE
+ otherwise. */
+
+bool
+linemap_location_from_macro_expansion_p (struct line_maps *set,
+ source_location location)
+{
+ linemap_assert (location <= MAX_SOURCE_LOCATION
+ && (set->highest_location
+ < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
+ if (set == NULL)
+ return false;
+ return (location > set->highest_location);
+}
+
+/* Given two virtual locations *LOC0 and *LOC1, return the first
+ common macro map in their macro expansion histories. Return NULL
+ if no common macro was found. *LOC0 (resp. *LOC1) is set to the
+ virtual location of the token inside the resulting macro. */
+
+static const struct line_map*
+first_map_in_common_1 (struct line_maps *set,
+ source_location *loc0,
+ source_location *loc1)
+{
+ source_location l0 = *loc0, l1 = *loc1;
+ const struct line_map *map0 = linemap_lookup (set, l0),
+ *map1 = linemap_lookup (set, l1);
+
+ while (linemap_macro_expansion_map_p (map0)
+ && linemap_macro_expansion_map_p (map1)
+ && (map0 != map1))
+ {
+ if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1))
+ {
+ l0 = linemap_macro_map_loc_to_exp_point (map0, l0);
+ map0 = linemap_lookup (set, l0);
+ }
+ else
+ {
+ l1 = linemap_macro_map_loc_to_exp_point (map1, l1);
+ map1 = linemap_lookup (set, l1);
+ }
+ }
+
+ if (map0 == map1)
+ {
+ *loc0 = l0;
+ *loc1 = l1;
+ return map0;
+ }
+ return NULL;
+}
+
+/* Given two virtual locations LOC0 and LOC1, return the first common
+ macro map in their macro expansion histories. Return NULL if no
+ common macro was found. *RES_LOC0 (resp. *RES_LOC1) is set to the
+ virtual location of the token inside the resulting macro, upon
+ return of a non-NULL result. */
+
+static const struct line_map*
+first_map_in_common (struct line_maps *set,
+ source_location loc0,
+ source_location loc1,
+ source_location *res_loc0,
+ source_location *res_loc1)
+{
+ *res_loc0 = loc0;
+ *res_loc1 = loc1;
+
+ return first_map_in_common_1 (set, res_loc0, res_loc1);
+}
+
+/* Return a positive value if PRE denotes the location of a token that
+ comes before the token of POST, 0 if PRE denotes the location of
+ the same token as the token for POST, and a negative value
+ otherwise. */
+
+int
+linemap_compare_locations (struct line_maps *set,
+ source_location pre,
+ source_location post)
+{
+ bool pre_virtual_p, post_virtual_p;
+ source_location l0 = pre, l1 = post;
+
+ if (l0 == l1)
+ return 0;
+
+ if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0)))
+ l0 = linemap_resolve_location (set, l0,
+ LRK_MACRO_EXPANSION_POINT,
+ NULL);
+
+ if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1)))
+ l1 = linemap_resolve_location (set, l1,
+ LRK_MACRO_EXPANSION_POINT,
+ NULL);
+
+ if (l0 == l1
+ && pre_virtual_p
+ && post_virtual_p)
+ {
+ /* So pre and post represent two tokens that are present in a
+ same macro expansion. Let's see if the token for pre was
+ before the token for post in that expansion. */
+ unsigned i0, i1;
+ const struct line_map *map =
+ first_map_in_common (set, pre, post, &l0, &l1);
+
+ if (map == NULL)
+ /* This should not be possible. */
+ abort ();
+
+ i0 = l0 - MAP_START_LOCATION (map);
+ i1 = l1 - MAP_START_LOCATION (map);
+ return i1 - i0;
+ }
+
+ return l1 - l0;
}
/* Print an include trace, for e.g. the -H option of the preprocessor. */
@@ -313,5 +896,338 @@ trace_include (const struct line_maps *set, const struct line_map *map)
while (--i)
putc ('.', stderr);
- fprintf (stderr, " %s\n", map->to_file);
+
+ fprintf (stderr, " %s\n", ORDINARY_MAP_FILE_NAME (map));
+}
+
+/* Return the spelling location of the token wherever it comes from,
+ whether part of a macro definition or not.
+
+ This is a subroutine for linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_spelling_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+
+ location =
+ linemap_macro_map_loc_unwind_toward_spelling (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- as part of a macro expansion -- then
+ return the location of the token at the definition point of the
+ macro. Otherwise, return LOCATION. SET is the set of maps
+ location come from. ORIGINAL_MAP is an output parm. If non NULL,
+ the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
+ returned location comes from.
+
+ This is a subroutine of linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_def_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+
+ location =
+ linemap_macro_map_loc_to_def_point (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- at a macro expansion point -- then return
+ the location of the topmost expansion point of the macro. We say
+ topmost because if we are in the context of a nested macro
+ expansion, the function returns the source location of the first
+ macro expansion that triggered the nested expansions.
+
+ Otherwise, return LOCATION. SET is the set of maps location come
+ from. ORIGINAL_MAP is an output parm. If non NULL, the function
+ sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
+ location comes from.
+
+ This is a subroutine of linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_exp_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+ location = linemap_macro_map_loc_to_exp_point (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* Resolve a virtual location into either a spelling location, an
+ expansion point location or a token argument replacement point
+ location. Return the map that encodes the virtual location as well
+ as the resolved location.
+
+ If LOC is *NOT* the location of a token resulting from the
+ expansion of a macro, then the parameter LRK (which stands for
+ Location Resolution Kind) is ignored and the resulting location
+ just equals the one given in argument.
+
+ Now if LOC *IS* the location of a token resulting from the
+ expansion of a macro, this is what happens.
+
+ * If LRK is set to LRK_MACRO_EXPANSION_POINT
+ -------------------------------
+
+ The virtual location is resolved to the location to the locus of
+ the expansion point of the macro.
+
+ * If LRK is set to LRK_SPELLING_LOCATION
+ -------------------------------------
+
+ The virtual location is resolved to the location to the locus where
+ the token has been spelled in the source. This can follow through
+ all the macro expansions that led to the token.
+
+ * If LRK is set to LRK_MACRO_PARM_REPLACEMENT_POINT
+ --------------------------------------
+
+ If LOC is the locus of a token that is an argument of a
+ function-like macro [replacing a parameter in the replacement list
+ of the macro] the virtual location is resolved to the locus of the
+ parameter that is replaced, in the context of the definition of the
+ macro.
+
+ If LOC is the locus of a token that is not an argument of a
+ function-like macro, then the function behaves as if LRK was set to
+ LRK_SPELLING_LOCATION.
+
+ If MAP is non-NULL, *MAP is set to the map of the resolved
+ location. */
+
+source_location
+linemap_resolve_location (struct line_maps *set,
+ source_location loc,
+ enum location_resolution_kind lrk,
+ const struct line_map **map)
+{
+ linemap_assert (set && loc >= RESERVED_LOCATION_COUNT);
+
+ switch (lrk)
+ {
+ case LRK_MACRO_EXPANSION_POINT:
+ loc = linemap_macro_loc_to_exp_point (set, loc, map);
+ break;
+ case LRK_SPELLING_LOCATION:
+ loc = linemap_macro_loc_to_spelling_point (set, loc, map);
+ break;
+ case LRK_MACRO_DEFINITION_LOCATION:
+ loc = linemap_macro_loc_to_def_point (set, loc, map);
+ break;
+ default:
+ abort ();
+ }
+ return loc;
+}
+
+/*
+ Suppose that LOC is the virtual location of a token T coming from
+ the expansion of a macro M. This function then steps up to get the
+ location L of the point where M got expanded. If L is a spelling
+ location inside a macro expansion M', then this function returns
+ the locus of the point where M' was expanded. Said otherwise, this
+ function returns the location of T in the context that triggered
+ the expansion of M.
+
+ *LOC_MAP must be set to the map of LOC. This function then sets it
+ to the map of the returned location. */
+
+source_location
+linemap_unwind_toward_expansion (struct line_maps *set,
+ source_location loc,
+ const struct line_map **map)
+{
+ source_location resolved_location;
+ const struct line_map *resolved_map;
+
+ resolved_location =
+ linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
+ resolved_map = linemap_lookup (set, resolved_location);
+
+ if (!linemap_macro_expansion_map_p (resolved_map))
+ {
+ resolved_location = linemap_macro_map_loc_to_exp_point (*map, loc);
+ resolved_map = linemap_lookup (set, resolved_location);
+ }
+
+ *map = resolved_map;
+ return resolved_location;
+}
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC must be a spelling (non-virtual) location. */
+
+expanded_location
+linemap_expand_location (const struct line_map *map,
+ source_location loc)
+
+{
+ expanded_location xloc;
+
+ xloc.file = LINEMAP_FILE (map);
+ xloc.line = SOURCE_LINE (map, loc);
+ xloc.column = SOURCE_COLUMN (map, loc);
+ xloc.sysp = LINEMAP_SYSP (map) != 0;
+
+ return xloc;
+}
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC can be a virtual location. The LRK parameter
+ is the same as for linemap_resolve_location. */
+
+expanded_location
+linemap_expand_location_full (struct line_maps *set,
+ source_location loc,
+ enum location_resolution_kind lrk)
+{
+ const struct line_map *map;
+ expanded_location xloc;
+
+ loc = linemap_resolve_location (set, loc, lrk, &map);
+ xloc = linemap_expand_location (map, loc);
+ return xloc;
+}
+
+/* Dump debugging information about source location LOC into the file
+ stream STREAM. SET is the line map set LOC comes from. */
+
+void
+linemap_dump_location (struct line_maps *set,
+ source_location loc,
+ FILE *stream)
+{
+ const struct line_map *map;
+ source_location location;
+ const char *path, *from;
+ int l,c,s,e;
+
+ if (loc == 0)
+ return;
+
+ location =
+ linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map);
+ path = LINEMAP_FILE (map);
+
+ l = SOURCE_LINE (map, location);
+ c = SOURCE_COLUMN (map, location);
+ s = LINEMAP_SYSP (map) != 0;
+ e = location != loc;
+
+ if (e)
+ from = "N/A";
+ else
+ from = (INCLUDED_FROM (set, map))
+ ? LINEMAP_FILE (INCLUDED_FROM (set, map))
+ : "<NULL>";
+
+ /* P: path, L: line, C: column, S: in-system-header, M: map address,
+ E: macro expansion?. */
+ fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d}",
+ path, from, l, c, s, (void*)map, e, loc);
+}
+
+/* Compute and return statistics about the memory consumption of some
+ parts of the line table SET. */
+
+void
+linemap_get_statistics (struct line_maps *set,
+ struct linemap_stats *s)
+{
+ long ordinary_maps_allocated_size, ordinary_maps_used_size,
+ macro_maps_allocated_size, macro_maps_used_size,
+ macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
+
+ struct line_map *cur_map;
+
+ ordinary_maps_allocated_size =
+ LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map);
+
+ ordinary_maps_used_size =
+ LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map);
+
+ macro_maps_allocated_size =
+ LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map);
+
+ for (cur_map = LINEMAPS_MACRO_MAPS (set);
+ cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
+ ++cur_map)
+ {
+ unsigned i;
+
+ linemap_assert (linemap_macro_expansion_map_p (cur_map));
+
+ macro_maps_locations_size +=
+ 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map) * sizeof (source_location);
+
+ for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map); i += 2)
+ {
+ if (MACRO_MAP_LOCATIONS (cur_map)[i] ==
+ MACRO_MAP_LOCATIONS (cur_map)[i + 1])
+ duplicated_macro_maps_locations_size +=
+ sizeof (source_location);
+ }
+ }
+
+ macro_maps_used_size =
+ LINEMAPS_MACRO_USED (set) * sizeof (struct line_map);
+
+ s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
+ s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
+ s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
+ s->ordinary_maps_used_size = ordinary_maps_used_size;
+ s->num_expanded_macros = num_expanded_macros_counter;
+ s->num_macro_tokens = num_macro_tokens_counter;
+ s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
+ s->macro_maps_allocated_size = macro_maps_allocated_size;
+ s->macro_maps_locations_size = macro_maps_locations_size;
+ s->macro_maps_used_size = macro_maps_used_size;
+ s->duplicated_macro_maps_locations_size =
+ duplicated_macro_maps_locations_size;
}
diff --git a/libcpp/macro.c b/libcpp/macro.c
index eba2349954a..f3139590d50 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -1,7 +1,7 @@
/* Part of CPP library. (Macro and #define handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -30,6 +30,10 @@ along with this program; see the file COPYING3. If not see
#include "internal.h"
typedef struct macro_arg macro_arg;
+/* This structure represents the tokens of a macro argument. These
+ tokens can be macro themselves, in which case they can be either
+ expanded or unexpanded. When they are expanded, this data
+ structure keeps both the expanded and unexpanded forms. */
struct macro_arg
{
const cpp_token **first; /* First token in unexpanded argument. */
@@ -37,17 +41,59 @@ struct macro_arg
const cpp_token *stringified; /* Stringified argument. */
unsigned int count; /* # of tokens in argument. */
unsigned int expanded_count; /* # of tokens in expanded argument. */
+ source_location *virt_locs; /* Where virtual locations for
+ unexpanded tokens are stored. */
+ source_location *expanded_virt_locs; /* Where virtual locations for
+ expanded tokens are
+ stored. */
+};
+
+/* The kind of macro tokens which the instance of
+ macro_arg_token_iter is supposed to iterate over. */
+enum macro_arg_token_kind {
+ MACRO_ARG_TOKEN_NORMAL,
+ /* This is a macro argument token that got transformed into a string
+ litteral, e.g. #foo. */
+ MACRO_ARG_TOKEN_STRINGIFIED,
+ /* This is a token resulting from the expansion of a macro
+ argument that was itself a macro. */
+ MACRO_ARG_TOKEN_EXPANDED
+};
+
+/* An iterator over tokens coming from a function-like macro
+ argument. */
+typedef struct macro_arg_token_iter macro_arg_token_iter;
+struct macro_arg_token_iter
+{
+ /* Whether or not -ftrack-macro-expansion is used. */
+ bool track_macro_exp_p;
+ /* The kind of token over which we are supposed to iterate. */
+ enum macro_arg_token_kind kind;
+ /* A pointer to the current token pointed to by the iterator. */
+ const cpp_token **token_ptr;
+ /* A pointer to the "full" location of the current token. If
+ -ftrack-macro-expansion is used this location tracks loci accross
+ macro expansion. */
+ const source_location *location_ptr;
+#ifdef ENABLE_CHECKING
+ /* The number of times the iterator went forward. This useful only
+ when checking is enabled. */
+ size_t num_forwards;
+#endif
};
/* Macro expansion. */
static int enter_macro_context (cpp_reader *, cpp_hashnode *,
- const cpp_token *);
+ const cpp_token *, source_location);
static int builtin_macro (cpp_reader *, cpp_hashnode *);
static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
const cpp_token **, unsigned int);
+static void push_extended_tokens_context (cpp_reader *, cpp_hashnode *,
+ _cpp_buff *, source_location *,
+ const cpp_token **, unsigned int);
static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
- _cpp_buff **);
+ _cpp_buff **, unsigned *);
static cpp_context *next_context (cpp_reader *);
static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
static void expand_arg (cpp_reader *, macro_arg *);
@@ -55,10 +101,53 @@ static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int);
static const cpp_token *stringify_arg (cpp_reader *, macro_arg *);
static void paste_all_tokens (cpp_reader *, const cpp_token *);
static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
+static void alloc_expanded_arg_mem (cpp_reader *, macro_arg *, size_t);
+static void ensure_expanded_arg_room (cpp_reader *, macro_arg *, size_t, size_t *);
+static void delete_macro_args (_cpp_buff*, unsigned num_args);
+static void set_arg_token (macro_arg *, const cpp_token *,
+ source_location, size_t,
+ enum macro_arg_token_kind,
+ bool);
+static const source_location *get_arg_token_location (const macro_arg *,
+ enum macro_arg_token_kind);
+static const cpp_token **arg_token_ptr_at (const macro_arg *,
+ size_t,
+ enum macro_arg_token_kind,
+ source_location **virt_location);
+
+static void macro_arg_token_iter_init (macro_arg_token_iter *, bool,
+ enum macro_arg_token_kind,
+ const macro_arg *,
+ const cpp_token **);
+static const cpp_token *macro_arg_token_iter_get_token
+(const macro_arg_token_iter *it);
+static source_location macro_arg_token_iter_get_location
+(const macro_arg_token_iter *);
+static void macro_arg_token_iter_forward (macro_arg_token_iter *);
+static _cpp_buff *tokens_buff_new (cpp_reader *, size_t,
+ source_location **);
+static size_t tokens_buff_count (_cpp_buff *);
+static const cpp_token **tokens_buff_last_token_ptr (_cpp_buff *);
+static const cpp_token **tokens_buff_put_token_to (const cpp_token **,
+ source_location *,
+ const cpp_token *,
+ source_location,
+ source_location,
+ const struct line_map *,
+ unsigned int);
+
+static const cpp_token **tokens_buff_add_token (_cpp_buff *,
+ source_location *,
+ const cpp_token *,
+ source_location,
+ source_location,
+ const struct line_map *,
+ unsigned int);
+static void tokens_buff_remove_last_token (_cpp_buff *);
static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
- macro_arg *);
+ macro_arg *, source_location);
static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *,
- _cpp_buff **);
+ _cpp_buff **, unsigned *);
static bool create_iso_definition (cpp_reader *, cpp_macro *);
/* #define directive parsing and handling. */
@@ -70,6 +159,18 @@ static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *,
static bool parse_params (cpp_reader *, cpp_macro *);
static void check_trad_stringification (cpp_reader *, const cpp_macro *,
const cpp_string *);
+static bool reached_end_of_context (cpp_context *);
+static void consume_next_token_from_context (cpp_reader *pfile,
+ const cpp_token **,
+ source_location *);
+static const cpp_token* cpp_get_token_1 (cpp_reader *, source_location *);
+
+/* Statistical counter tracking the number of macros that got
+ expanded. */
+unsigned num_expanded_macros_counter = 0;
+/* Statistical counter tracking the total number tokens resulting
+ from macro expansion. */
+unsigned num_macro_tokens_counter = 0;
/* Emits a warning if NODE is a macro defined in the main file that
has not been used. */
@@ -171,13 +272,17 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
unsigned int len;
const char *name;
uchar *buf;
- map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line);
-
- if (node->value.builtin == BT_BASE_FILE)
- while (! MAIN_FILE_P (map))
- map = INCLUDED_FROM (pfile->line_table, map);
-
- name = map->to_file;
+
+ if (node->value.builtin == BT_FILE)
+ name = linemap_get_expansion_filename (pfile->line_table,
+ pfile->line_table->highest_line);
+ else
+ {
+ map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line);
+ while (! MAIN_FILE_P (map))
+ map = INCLUDED_FROM (pfile->line_table, map);
+ name = ORDINARY_MAP_FILE_NAME (map);
+ }
len = strlen (name);
buf = _cpp_unaligned_alloc (pfile, len * 2 + 3);
result = buf;
@@ -196,14 +301,14 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
break;
case BT_SPECLINE:
- map = &pfile->line_table->maps[pfile->line_table->used-1];
+ map = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table);
/* If __LINE__ is embedded in a macro, it must expand to the
line of the macro's invocation, not its definition.
Otherwise things like assert() will not work properly. */
- number = SOURCE_LINE (map,
- CPP_OPTION (pfile, traditional)
- ? pfile->line_table->highest_line
- : pfile->cur_token[-1].src_loc);
+ number = linemap_get_expansion_line (pfile->line_table,
+ CPP_OPTION (pfile, traditional)
+ ? pfile->line_table->highest_line
+ : pfile->cur_token[-1].src_loc);
break;
/* __STDC__ has the value 1 under normal circumstances.
@@ -507,7 +612,7 @@ paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
static void
paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
{
- const cpp_token *rhs;
+ const cpp_token *rhs = NULL;
cpp_context *context = pfile->context;
do
@@ -517,10 +622,25 @@ paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
object-like macro, or a function-like macro with arguments
inserted. In either case, the constraints to #define
guarantee we have at least one more token. */
- if (context->direct_p)
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
rhs = FIRST (context).token++;
- else
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT)
rhs = *FIRST (context).ptoken++;
+ else if (context->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ /* So we are in presence of an extended token context, which
+ means that each token in this context has a virtual
+ location attached to it. So let's not forget to update
+ the pointer to the current virtual location of the
+ current token when we update the pointer to the current
+ token */
+
+ rhs = *FIRST (context).ptoken++;
+ /* context->c.mc must be non-null, as if we were not in a
+ macro context, context->tokens_kind could not be equal to
+ TOKENS_KIND_EXTENDED. */
+ context->c.mc->cur_virt_loc++;
+ }
if (rhs->type == CPP_PADDING)
{
@@ -584,23 +704,37 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node
NULL. Each argument is terminated by a CPP_EOF token, for the
future benefit of expand_arg(). If there are any deferred
#pragma directives among macro arguments, store pointers to the
- CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer. */
+ CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer.
+
+ What is returned is the buffer that contains the memory allocated
+ to hold the macro arguments. NODE is the name of the macro this
+ function is dealing with. If NUM_ARGS is non-NULL, *NUM_ARGS is
+ set to the actual number of macro arguments allocated in the
+ returned buffer. */
static _cpp_buff *
collect_args (cpp_reader *pfile, const cpp_hashnode *node,
- _cpp_buff **pragma_buff)
+ _cpp_buff **pragma_buff, unsigned *num_args)
{
_cpp_buff *buff, *base_buff;
cpp_macro *macro;
macro_arg *args, *arg;
const cpp_token *token;
unsigned int argc;
+ source_location virt_loc;
+ bool track_macro_expansion_p = CPP_OPTION (pfile, track_macro_expansion);
+ unsigned num_args_alloced = 0;
macro = node->value.macro;
if (macro->paramc)
argc = macro->paramc;
else
argc = 1;
- buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *)
+
+#define DEFAULT_NUM_TOKENS_PER_MACRO_ARG 50
+#define ARG_TOKENS_EXTENT 1000
+
+ buff = _cpp_get_buff (pfile, argc * (DEFAULT_NUM_TOKENS_PER_MACRO_ARG
+ * sizeof (cpp_token *)
+ sizeof (macro_arg)));
base_buff = buff;
args = (macro_arg *) buff->base;
@@ -615,9 +749,17 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
{
unsigned int paren_depth = 0;
unsigned int ntokens = 0;
+ unsigned virt_locs_capacity = DEFAULT_NUM_TOKENS_PER_MACRO_ARG;
+ num_args_alloced++;
argc++;
arg->first = (const cpp_token **) buff->cur;
+ if (track_macro_expansion_p)
+ {
+ virt_locs_capacity = DEFAULT_NUM_TOKENS_PER_MACRO_ARG;
+ arg->virt_locs = XNEWVEC (source_location,
+ virt_locs_capacity);
+ }
for (;;)
{
@@ -625,11 +767,20 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit)
{
buff = _cpp_append_extend_buff (pfile, buff,
- 1000 * sizeof (cpp_token *));
+ ARG_TOKENS_EXTENT
+ * sizeof (cpp_token *));
arg->first = (const cpp_token **) buff->cur;
}
+ if (track_macro_expansion_p
+ && (ntokens + 2 > virt_locs_capacity))
+ {
+ virt_locs_capacity += ARG_TOKENS_EXTENT;
+ arg->virt_locs = XRESIZEVEC (source_location,
+ arg->virt_locs,
+ virt_locs_capacity);
+ }
- token = cpp_get_token (pfile);
+ token = cpp_get_token_1 (pfile, &virt_loc);
if (token->type == CPP_PADDING)
{
@@ -686,7 +837,7 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
BUFF_FRONT (*pragma_buff) += sizeof (cpp_token *);
if (token->type == CPP_PRAGMA_EOL)
break;
- token = cpp_get_token (pfile);
+ token = cpp_get_token_1 (pfile, &virt_loc);
}
while (token->type != CPP_EOF);
@@ -700,8 +851,10 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
else
continue;
}
-
- arg->first[ntokens++] = token;
+ set_arg_token (arg, token, virt_loc,
+ ntokens, MACRO_ARG_TOKEN_NORMAL,
+ CPP_OPTION (pfile, track_macro_expansion));
+ ntokens++;
}
/* Drop trailing padding. */
@@ -709,7 +862,9 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
ntokens--;
arg->count = ntokens;
- arg->first[ntokens] = &pfile->eof;
+ set_arg_token (arg, &pfile->eof, pfile->eof.src_loc,
+ ntokens, MACRO_ARG_TOKEN_NORMAL,
+ CPP_OPTION (pfile, track_macro_expansion));
/* Terminate the argument. Excess arguments loop back and
overwrite the final legitimate argument, before failing. */
@@ -752,6 +907,8 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
|| (argc == 1 && args[0].count == 0
&& !CPP_OPTION (pfile, std))))
args[macro->paramc - 1].first = NULL;
+ if (num_args)
+ *num_args = num_args_alloced;
return base_buff;
}
}
@@ -765,10 +922,12 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
way that, if none is found, we don't lose the information in any
intervening padding tokens. If we find the parenthesis, collect
the arguments and return the buffer containing them. PRAGMA_BUFF
- argument is the same as in collect_args. */
+ argument is the same as in collect_args. If NUM_ARGS is non-NULL,
+ *NUM_ARGS is set to the number of arguments contained in the
+ returned buffer. */
static _cpp_buff *
funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
- _cpp_buff **pragma_buff)
+ _cpp_buff **pragma_buff, unsigned *num_args)
{
const cpp_token *token, *padding = NULL;
@@ -785,7 +944,7 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
if (token->type == CPP_OPEN_PAREN)
{
pfile->state.parsing_args = 2;
- return collect_args (pfile, node, pragma_buff);
+ return collect_args (pfile, node, pragma_buff, num_args);
}
/* CPP_EOF can be the end of macro arguments, or the end of the
@@ -819,13 +978,15 @@ macro_real_token_count (const cpp_macro *macro)
/* Push the context of a macro with hash entry NODE onto the context
stack. If we can successfully expand the macro, we push a context
containing its yet-to-be-rescanned replacement list and return one.
- If there were additionally any unexpanded deferred #pragma directives
- among macro arguments, push another context containing the
- pragma tokens before the yet-to-be-rescanned replacement list
- and return two. Otherwise, we don't push a context and return zero. */
+ If there were additionally any unexpanded deferred #pragma
+ directives among macro arguments, push another context containing
+ the pragma tokens before the yet-to-be-rescanned replacement list
+ and return two. Otherwise, we don't push a context and return
+ zero. LOCATION is the location of the expansion point of the
+ macro. */
static int
enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
- const cpp_token *result)
+ const cpp_token *result, source_location location)
{
/* The presence of a macro invalidates a file's controlling macro. */
pfile->mi_valid = false;
@@ -850,11 +1011,13 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
if (macro->fun_like)
{
_cpp_buff *buff;
+ unsigned num_args = 0;
pfile->state.prevent_expansion++;
pfile->keep_tokens++;
pfile->state.parsing_args = 1;
- buff = funlike_invocation_p (pfile, node, &pragma_buff);
+ buff = funlike_invocation_p (pfile, node, &pragma_buff,
+ &num_args);
pfile->state.parsing_args = 0;
pfile->keep_tokens--;
pfile->state.prevent_expansion--;
@@ -873,8 +1036,13 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
}
if (macro->paramc > 0)
- replace_args (pfile, node, macro, (macro_arg *) buff->base);
- _cpp_release_buff (pfile, buff);
+ replace_args (pfile, node, macro,
+ (macro_arg *) buff->base,
+ location);
+ /* Free the memory used by the arguments of this
+ function-like macro. This memory has been allocated by
+ funlike_invocation_p and by replace_args. */
+ delete_macro_args (buff, num_args);
}
/* Disable the macro within its expansion. */
@@ -888,13 +1056,49 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
}
if (pfile->cb.used)
- pfile->cb.used (pfile, result->src_loc, node);
+ pfile->cb.used (pfile, location, node);
macro->used = 1;
if (macro->paramc == 0)
- _cpp_push_token_context (pfile, node, macro->exp.tokens,
- macro_real_token_count (macro));
+ {
+ if (CPP_OPTION (pfile, track_macro_expansion))
+ {
+ unsigned int i, count = macro->count;
+ const cpp_token *src = macro->exp.tokens;
+ const struct line_map *map;
+ source_location *virt_locs = NULL;
+ _cpp_buff *macro_tokens =
+ tokens_buff_new (pfile, count, &virt_locs);
+
+ /* Create a macro map to record the locations of the
+ tokens that are involved in the expansion. LOCATION
+ is the location of the macro expansion point. */
+ map = linemap_enter_macro (pfile->line_table,
+ node, location, count);
+ for (i = 0; i < count; ++i)
+ {
+ tokens_buff_add_token (macro_tokens, virt_locs,
+ src, src->src_loc,
+ src->src_loc, map, i);
+ ++src;
+ }
+ push_extended_tokens_context (pfile, node,
+ macro_tokens,
+ virt_locs,
+ (const cpp_token **)
+ macro_tokens->base,
+ count);
+ num_macro_tokens_counter += count;
+ }
+ else
+ {
+ unsigned tokens_count = macro_real_token_count (macro);
+ _cpp_push_token_context (pfile, node, macro->exp.tokens,
+ tokens_count);
+ num_macro_tokens_counter += tokens_count;
+ }
+ }
if (pragma_buff)
{
@@ -903,13 +1107,18 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
padding_token (pfile, result), 1);
do
{
+ unsigned tokens_count;
_cpp_buff *tail = pragma_buff->next;
pragma_buff->next = NULL;
+ tokens_count = ((const cpp_token **) BUFF_FRONT (pragma_buff)
+ - (const cpp_token **) pragma_buff->base);
push_ptoken_context (pfile, NULL, pragma_buff,
(const cpp_token **) pragma_buff->base,
- ((const cpp_token **) BUFF_FRONT (pragma_buff)
- - (const cpp_token **) pragma_buff->base));
+ tokens_count);
pragma_buff = tail;
+ if (!CPP_OPTION (pfile, track_macro_expansion))
+ num_macro_tokens_counter += tokens_count;
+
}
while (pragma_buff != NULL);
return 2;
@@ -922,33 +1131,318 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
return builtin_macro (pfile, node);
}
+/* De-allocate the memory used by BUFF which is an array of instances
+ of macro_arg. NUM_ARGS is the number of instances of macro_arg
+ present in BUFF. */
+static void
+delete_macro_args (_cpp_buff *buff, unsigned num_args)
+{
+ macro_arg *macro_args;
+ unsigned i;
+
+ if (buff == NULL)
+ return;
+
+ macro_args = (macro_arg *) buff->base;
+
+ /* Walk instances of macro_arg to free their expanded tokens as well
+ as their macro_arg::virt_locs members. */
+ for (i = 0; i < num_args; ++i)
+ {
+ if (macro_args[i].expanded)
+ {
+ free (macro_args[i].expanded);
+ macro_args[i].expanded = NULL;
+ }
+ if (macro_args[i].virt_locs)
+ {
+ free (macro_args[i].virt_locs);
+ macro_args[i].virt_locs = NULL;
+ }
+ if (macro_args[i].expanded_virt_locs)
+ {
+ free (macro_args[i].expanded_virt_locs);
+ macro_args[i].expanded_virt_locs = NULL;
+ }
+ }
+ _cpp_free_buff (buff);
+}
+
+/* Set the INDEXth token of the macro argument ARG. TOKEN is the token
+ to set, LOCATION is its virtual location. "Virtual" location means
+ the location that encodes loci accross macro expansion. Otherwise
+ it has to be TOKEN->SRC_LOC. KIND is the kind of tokens the
+ argument ARG is supposed to contain. Note that ARG must be
+ tailored so that it has enough room to contain INDEX + 1 numbers of
+ tokens, at least. */
+static void
+set_arg_token (macro_arg *arg, const cpp_token *token,
+ source_location location, size_t index,
+ enum macro_arg_token_kind kind,
+ bool track_macro_exp_p)
+{
+ const cpp_token **token_ptr;
+ source_location *loc = NULL;
+
+ token_ptr =
+ arg_token_ptr_at (arg, index, kind,
+ track_macro_exp_p ? &loc : NULL);
+ *token_ptr = token;
+
+ if (loc != NULL)
+ {
+#ifdef ENABLE_CHECKING
+ if (kind == MACRO_ARG_TOKEN_STRINGIFIED
+ || !track_macro_exp_p)
+ /* We can't set the location of a stringified argument
+ token and we can't set any location if we aren't tracking
+ macro expansion locations. */
+ abort ();
+#endif
+ *loc = location;
+ }
+}
+
+/* Get the pointer to the location of the argument token of the
+ function-like macro argument ARG. This function must be called
+ only when we -ftrack-macro-expansion is on. */
+static const source_location *
+get_arg_token_location (const macro_arg *arg,
+ enum macro_arg_token_kind kind)
+{
+ const source_location *loc = NULL;
+ const cpp_token **token_ptr =
+ arg_token_ptr_at (arg, 0, kind, (source_location **) &loc);
+
+ if (token_ptr == NULL)
+ return NULL;
+
+ return loc;
+}
+
+/* Return the pointer to the INDEXth token of the macro argument ARG.
+ KIND specifies the kind of token the macro argument ARG contains.
+ If VIRT_LOCATION is non NULL, *VIRT_LOCATION is set to the address
+ of the virtual location of the returned token if the
+ -ftrack-macro-expansion flag is on; otherwise, it's set to the
+ spelling location of the returned token. */
+static const cpp_token **
+arg_token_ptr_at (const macro_arg *arg, size_t index,
+ enum macro_arg_token_kind kind,
+ source_location **virt_location)
+{
+ const cpp_token **tokens_ptr = NULL;
+
+ switch (kind)
+ {
+ case MACRO_ARG_TOKEN_NORMAL:
+ tokens_ptr = arg->first;
+ break;
+ case MACRO_ARG_TOKEN_STRINGIFIED:
+ tokens_ptr = (const cpp_token **) &arg->stringified;
+ break;
+ case MACRO_ARG_TOKEN_EXPANDED:
+ tokens_ptr = arg->expanded;
+ break;
+ }
+
+ if (tokens_ptr == NULL)
+ /* This can happen for e.g, an empty token argument to a
+ funtion-like macro. */
+ return tokens_ptr;
+
+ if (virt_location)
+ {
+ if (kind == MACRO_ARG_TOKEN_NORMAL)
+ *virt_location = &arg->virt_locs[index];
+ else if (kind == MACRO_ARG_TOKEN_EXPANDED)
+ *virt_location = &arg->expanded_virt_locs[index];
+ else if (kind == MACRO_ARG_TOKEN_STRINGIFIED)
+ *virt_location =
+ (source_location *) &tokens_ptr[index]->src_loc;
+ }
+ return &tokens_ptr[index];
+}
+
+/* Initialize an iterator so that it iterates over the tokens of a
+ function-like macro argument. KIND is the kind of tokens we want
+ ITER to iterate over. TOKEN_PTR points the first token ITER will
+ iterate over. */
+static void
+macro_arg_token_iter_init (macro_arg_token_iter *iter,
+ bool track_macro_exp_p,
+ enum macro_arg_token_kind kind,
+ const macro_arg *arg,
+ const cpp_token **token_ptr)
+{
+ iter->track_macro_exp_p = track_macro_exp_p;
+ iter->kind = kind;
+ iter->token_ptr = token_ptr;
+ /* Unconditionally initialize this so that the compiler doesn't warn
+ about iter->location_ptr being possibly uninitialized later after
+ this code has been inlined somewhere. */
+ iter->location_ptr = NULL;
+ if (track_macro_exp_p)
+ iter->location_ptr = get_arg_token_location (arg, kind);
+#ifdef ENABLE_CHECKING
+ iter->num_forwards = 0;
+ if (track_macro_exp_p
+ && token_ptr != NULL
+ && iter->location_ptr == NULL)
+ abort ();
+#endif
+}
+
+/* Move the iterator one token forward. Note that if IT was
+ initialized on an argument that has a stringified token, moving it
+ foward doesn't make sense as a stringified token is essentially one
+ string. */
+static void
+macro_arg_token_iter_forward (macro_arg_token_iter *it)
+{
+ switch (it->kind)
+ {
+ case MACRO_ARG_TOKEN_NORMAL:
+ case MACRO_ARG_TOKEN_EXPANDED:
+ it->token_ptr++;
+ if (it->track_macro_exp_p)
+ it->location_ptr++;
+ break;
+ case MACRO_ARG_TOKEN_STRINGIFIED:
+#ifdef ENABLE_CHECKING
+ if (it->num_forwards > 0)
+ abort ();
+#endif
+ break;
+ }
+
+#ifdef ENABLE_CHECKING
+ it->num_forwards++;
+#endif
+}
+
+/* Return the token pointed to by the iterator. */
+static const cpp_token *
+macro_arg_token_iter_get_token (const macro_arg_token_iter *it)
+{
+#ifdef ENABLE_CHECKING
+ if (it->kind == MACRO_ARG_TOKEN_STRINGIFIED
+ && it->num_forwards > 0)
+ abort ();
+#endif
+ if (it->token_ptr == NULL)
+ return NULL;
+ return *it->token_ptr;
+}
+
+/* Return the location of the token pointed to by the iterator.*/
+static source_location
+macro_arg_token_iter_get_location (const macro_arg_token_iter *it)
+{
+#ifdef ENABLE_CHECKING
+ if (it->kind == MACRO_ARG_TOKEN_STRINGIFIED
+ && it->num_forwards > 0)
+ abort ();
+#endif
+ if (it->track_macro_exp_p)
+ return *it->location_ptr;
+ else
+ return (*it->token_ptr)->src_loc;
+}
+
+/* Return the index of a token [resulting from macro expansion] inside
+ the total list of tokens resulting from a given macro
+ expansion. The index can be different depending on whether if we
+ want each tokens resulting from function-like macro arguments
+ expansion to have a different location or not.
+
+ E.g, consider this function-like macro:
+
+ #define M(x) x - 3
+
+ Then consider us "calling" it (and thus expanding it) like:
+
+ M(1+4)
+
+ It will be expanded into:
+
+ 1+4-3
+
+ Let's consider the case of the token '4'.
+
+ Its index can be 2 (it's the third token of the set of tokens
+ resulting from the expansion) or it can be 0 if we consider that
+ all tokens resulting from the expansion of the argument "1+2" have
+ the same index, which is 0. In this later case, the index of token
+ '-' would then be 1 and the index of token '3' would be 2.
+
+ The later case is useful to use less memory e.g, for the case of
+ the user using the option -ftrack-macro-expansion=1.
+
+ ABSOLUTE_TOKEN_INDEX is the index of the macro argument token we
+ are interested in. CUR_REPLACEMENT_TOKEN is the token of the macro
+ parameter (inside the macro replacement list) that corresponds to
+ the macro argument for which ABSOLUTE_TOKEN_INDEX is a token index
+ of.
+
+ If we refer to the example above, for the '4' argument token,
+ ABSOLUTE_TOKEN_INDEX would be set to 2, and CUR_REPLACEMENT_TOKEN
+ would be set to the token 'x', in the replacement list "x - 3" of
+ macro M.
+
+ This is a subroutine of replace_args. */
+inline static unsigned
+expanded_token_index (cpp_reader *pfile, cpp_macro *macro,
+ const cpp_token *cur_replacement_token,
+ unsigned absolute_token_index)
+{
+ if (CPP_OPTION (pfile, track_macro_expansion) > 1)
+ return absolute_token_index;
+ return cur_replacement_token - macro->exp.tokens;
+}
+
/* Replace the parameters in a function-like macro of NODE with the
actual ARGS, and place the result in a newly pushed token context.
Expand each argument before replacing, unless it is operated upon
- by the # or ## operators. */
+ by the # or ## operators. EXPANSION_POINT_LOC is the location of
+ the expansion point of the macro. E.g, the location of the
+ function-like macro invocation. */
static void
-replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg *args)
+replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
+ macro_arg *args, source_location expansion_point_loc)
{
unsigned int i, total;
const cpp_token *src, *limit;
- const cpp_token **dest, **first;
+ const cpp_token **first = NULL;
macro_arg *arg;
- _cpp_buff *buff;
- unsigned int count;
+ _cpp_buff *buff = NULL;
+ source_location *virt_locs = NULL;
+ unsigned int exp_count;
+ const struct line_map *map = NULL;
+ int track_macro_exp;
/* First, fully macro-expand arguments, calculating the number of
tokens in the final expansion as we go. The ordering of the if
statements below is subtle; we must handle stringification before
pasting. */
- count = macro_real_token_count (macro);
- total = count;
- limit = macro->exp.tokens + count;
+
+ /* EXP_COUNT is the number of tokens in the macro replacement
+ list. TOTAL is the number of tokens /after/ macro parameters
+ have been replaced by their arguments. */
+ exp_count = macro_real_token_count (macro);
+ total = exp_count;
+ limit = macro->exp.tokens + exp_count;
for (src = macro->exp.tokens; src < limit; src++)
if (src->type == CPP_MACRO_ARG)
{
/* Leading and trailing padding tokens. */
total += 2;
+ /* Account for leading and padding tokens in exp_count too.
+ This is going to be important later down this function,
+ when we want to handle the case of (track_macro_exp <
+ 2). */
+ exp_count += 2;
/* We have an argument. If it is not being stringified or
pasted it is macro-replaced before insertion. */
@@ -970,67 +1464,230 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
}
}
- /* Now allocate space for the expansion, copy the tokens and replace
- the arguments. */
- buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *));
+ /* When the compiler is called with the -ftrack-macro-expansion
+ flag, we need to keep track of the location of each token that
+ results from macro expansion.
+
+ A token resulting from macro expansion is not a new token. It is
+ simply the same token as the token coming from the macro
+ definition. The new things that are allocated are the buffer
+ that holds the tokens resulting from macro expansion and a new
+ location that records many things like the locus of the expansion
+ point as well as the original locus inside the definition of the
+ macro. This location is called a virtual location.
+
+ So the buffer BUFF holds a set of cpp_token*, and the buffer
+ VIRT_LOCS holds the virtual locations of the tokens held by BUFF.
+
+ Both of these two buffers are going to be hung off of the macro
+ context, when the latter is pushed. The memory allocated to
+ store the tokens and their locations is going to be freed once
+ the context of macro expansion is popped.
+
+ As far as tokens are concerned, the memory overhead of
+ -ftrack-macro-expansion is proportional to the number of
+ macros that get expanded multiplied by sizeof (source_location).
+ The good news is that extra memory gets freed when the macro
+ context is freed, i.e shortly after the macro got expanded. */
+
+ /* Is the -ftrack-macro-expansion flag in effect? */
+ track_macro_exp = CPP_OPTION (pfile, track_macro_expansion);
+
+ /* Now allocate memory space for tokens and locations resulting from
+ the macro expansion, copy the tokens and replace the arguments.
+ This memory must be freed when the context of the macro MACRO is
+ popped. */
+ buff = tokens_buff_new (pfile, total, track_macro_exp ? &virt_locs : NULL);
+
first = (const cpp_token **) buff->base;
- dest = first;
+ /* Create a macro map to record the locations of the tokens that are
+ involved in the expansion. Note that the expansion point is set
+ to the location of the closing parenthesis. Otherwise, the
+ subsequent map created for the first token that comes after the
+ macro map might have a wrong line number. That would lead to
+ tokens with wrong line numbers after the macro expansion. This
+ adds up to the memory overhead of the -ftrack-macro-expansion
+ flag; for every macro that is expanded, a "macro map" is
+ created. */
+ if (track_macro_exp)
+ {
+ int num_macro_tokens = total;
+ if (track_macro_exp < 2)
+ /* Then the number of macro tokens won't take in account the
+ fact that function-like macro arguments can expand to
+ multiple tokens. This is to save memory at the expense of
+ accuracy.
+
+ Suppose we have #define SQARE(A) A * A
+
+ And then we do SQARE(2+3)
+
+ Then the tokens 2, +, 3, will have the same location,
+ saying they come from the expansion of the argument A. */
+ num_macro_tokens = exp_count;
+ map = linemap_enter_macro (pfile->line_table, node,
+ expansion_point_loc,
+ num_macro_tokens);
+ }
+ i = 0;
for (src = macro->exp.tokens; src < limit; src++)
{
- unsigned int count;
- const cpp_token **from, **paste_flag;
+ unsigned int arg_tokens_count;
+ macro_arg_token_iter from;
+ const cpp_token **paste_flag = NULL;
+ const cpp_token **tmp_token_ptr;
if (src->type != CPP_MACRO_ARG)
{
- *dest++ = src;
+ /* Allocate a virtual location for token SRC, and add that
+ token and its virtual location into the buffers BUFF and
+ VIRT_LOCS. */
+ unsigned index = expanded_token_index (pfile, macro, src, i);
+ tokens_buff_add_token (buff, virt_locs, src,
+ src->src_loc, src->src_loc,
+ map, index);
+ i += 1;
continue;
}
paste_flag = 0;
arg = &args[src->val.macro_arg.arg_no - 1];
+ /* SRC is a macro parameter that we need to replace with its
+ corresponding argument. So at some point we'll need to
+ iterate over the tokens of the macro argument and copy them
+ into the "place" now holding the correspondig macro
+ parameter. We are going to use the iterator type
+ macro_argo_token_iter to handle that iterating. The 'if'
+ below is to initialize the iterator depending on the type of
+ tokens the macro argument has. It also does some adjustment
+ related to padding tokens and some pasting corner cases. */
if (src->flags & STRINGIFY_ARG)
- count = 1, from = &arg->stringified;
+ {
+ arg_tokens_count = 1;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_STRINGIFIED,
+ arg, &arg->stringified);
+ }
else if (src->flags & PASTE_LEFT)
- count = arg->count, from = arg->first;
+ {
+ arg_tokens_count = arg->count;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_NORMAL,
+ arg, arg->first);
+ }
else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))
{
- count = arg->count, from = arg->first;
- if (dest != first)
+ int num_toks;
+ arg_tokens_count = arg->count;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_NORMAL,
+ arg, arg->first);
+
+ num_toks = tokens_buff_count (buff);
+
+ if (num_toks != 0)
{
- if (dest[-1]->type == CPP_COMMA
+ /* So the current parameter token is pasted to the previous
+ token in the replacement list. Let's look at what
+ we have as previous and current arguments. */
+
+ /* This is the previous argument's token ... */
+ tmp_token_ptr = tokens_buff_last_token_ptr (buff);
+
+ if ((*tmp_token_ptr)->type == CPP_COMMA
&& macro->variadic
&& src->val.macro_arg.arg_no == macro->paramc)
{
- /* Swallow a pasted comma if from == NULL, otherwise
- drop the paste flag. */
- if (from == NULL)
- dest--;
+ /* ... which is a comma; and the current parameter
+ is the last parameter of a variadic function-like
+ macro. If the argument to the current last
+ parameter is NULL, then swallow the comma,
+ otherwise drop the paste flag. */
+ if (macro_arg_token_iter_get_token (&from) == NULL)
+ tokens_buff_remove_last_token (buff);
else
- paste_flag = dest - 1;
+ paste_flag = tmp_token_ptr;
}
/* Remove the paste flag if the RHS is a placemarker. */
- else if (count == 0)
- paste_flag = dest - 1;
+ else if (arg_tokens_count == 0)
+ paste_flag = tmp_token_ptr;
}
}
else
- count = arg->expanded_count, from = arg->expanded;
+ {
+ arg_tokens_count = arg->expanded_count;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_EXPANDED,
+ arg, arg->expanded);
+ }
/* Padding on the left of an argument (unless RHS of ##). */
if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
&& src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT))
- *dest++ = padding_token (pfile, src);
+ {
+ const cpp_token *t = padding_token (pfile, src);
+ unsigned index = expanded_token_index (pfile, macro, src, i);
+ /* Allocate a virtual location for the padding token and
+ append the token and its location to BUFF and
+ VIRT_LOCS. */
+ tokens_buff_add_token (buff, virt_locs, t,
+ t->src_loc, t->src_loc,
+ map, index);
+ }
- if (count)
+ if (arg_tokens_count)
{
- memcpy (dest, from, count * sizeof (cpp_token *));
- dest += count;
+ /* So now we've got the number of tokens that make up the
+ argument that is going to replace the current parameter
+ in the macro's replacement list. */
+ unsigned int j;
+ for (j = 0; j < arg_tokens_count; ++j)
+ {
+ /* So if track_macro_exp is < 2, the user wants to
+ save extra memory while tracking macro expansion
+ locations. So in that case here is what we do:
+
+ Suppose we have #define SQARE(A) A * A
+
+ And then we do SQARE(2+3)
+
+ Then the tokens 2, +, 3, will have the same location,
+ saying they come from the expansion of the argument
+ A.
+
+ So that means we are going to ignore the COUNT tokens
+ resulting from the expansion of the current macro
+ arugment. In other words all the ARG_TOKENS_COUNT tokens
+ resulting from the expansion of the macro argument will
+ have the index I. Normally, each of those token should
+ have index I+J. */
+ unsigned token_index = i;
+ unsigned index;
+ if (track_macro_exp > 1)
+ token_index += j;
+
+ index = expanded_token_index (pfile, macro, src, token_index);
+ tokens_buff_add_token (buff, virt_locs,
+ macro_arg_token_iter_get_token (&from),
+ macro_arg_token_iter_get_location (&from),
+ src->src_loc, map, index);
+ macro_arg_token_iter_forward (&from);
+ }
/* With a non-empty argument on the LHS of ##, the last
token should be flagged PASTE_LEFT. */
if (src->flags & PASTE_LEFT)
- paste_flag = dest - 1;
+ paste_flag =
+ (const cpp_token **) tokens_buff_last_token_ptr (buff);
}
else if (CPP_PEDANTIC (pfile) && ! macro->syshdr
&& ! CPP_OPTION (pfile, c99)
@@ -1046,7 +1703,12 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
/* Avoid paste on RHS (even case count == 0). */
if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
- *dest++ = &pfile->avoid_paste;
+ {
+ const cpp_token *t = &pfile->avoid_paste;
+ tokens_buff_add_token (buff, virt_locs,
+ t, t->src_loc, t->src_loc,
+ NULL, 0);
+ }
/* Add a new paste flag, or remove an unwanted one. */
if (paste_flag)
@@ -1060,13 +1722,18 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
token->flags = (*paste_flag)->flags & ~PASTE_LEFT;
*paste_flag = token;
}
+
+ i += arg_tokens_count;
}
- /* Free the expanded arguments. */
- for (i = 0; i < macro->paramc; i++)
- free (args[i].expanded);
+ if (track_macro_exp)
+ push_extended_tokens_context (pfile, node, buff, virt_locs, first,
+ tokens_buff_count (buff));
+ else
+ push_ptoken_context (pfile, node, buff, first,
+ tokens_buff_count (buff));
- push_ptoken_context (pfile, node, buff, first, dest - first);
+ num_macro_tokens_counter += tokens_buff_count (buff);
}
/* Return a special padding token, with padding inherited from SOURCE. */
@@ -1094,6 +1761,7 @@ next_context (cpp_reader *pfile)
if (result == 0)
{
result = XNEW (cpp_context);
+ memset (result, 0, sizeof (cpp_context));
result->prev = pfile->context;
result->next = 0;
pfile->context->next = result;
@@ -1110,8 +1778,8 @@ push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, _cpp_buff *buff,
{
cpp_context *context = next_context (pfile);
- context->direct_p = false;
- context->macro = macro;
+ context->tokens_kind = TOKENS_KIND_INDIRECT;
+ context->c.macro = macro;
context->buff = buff;
FIRST (context).ptoken = first;
LAST (context).ptoken = first + count;
@@ -1122,15 +1790,44 @@ void
_cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
const cpp_token *first, unsigned int count)
{
- cpp_context *context = next_context (pfile);
-
- context->direct_p = true;
- context->macro = macro;
- context->buff = NULL;
+ cpp_context *context = next_context (pfile);
+
+ context->tokens_kind = TOKENS_KIND_DIRECT;
+ context->c.macro = macro;
+ context->buff = NULL;
FIRST (context).token = first;
LAST (context).token = first + count;
}
+/* Build a context containing a list of tokens as well as their
+ virtual locations and push it. TOKENS_BUFF is the buffer that
+ contains the tokens pointed to by FIRST. If TOKENS_BUFF is
+ non-NULL, it means that the context owns it, meaning that
+ _cpp_pop_context will free it as well as VIRT_LOCS_BUFF that
+ contains the virtual locations. */
+static void
+push_extended_tokens_context (cpp_reader *pfile,
+ cpp_hashnode *macro,
+ _cpp_buff *token_buff,
+ source_location *virt_locs,
+ const cpp_token **first,
+ unsigned int count)
+{
+ cpp_context *context = next_context (pfile);
+ macro_context *m;
+
+ context->tokens_kind = TOKENS_KIND_EXTENDED;
+ context->buff = token_buff;
+
+ m = XNEW (macro_context);
+ m->macro_node = macro;
+ m->virt_locs = virt_locs;
+ m->cur_virt_loc = virt_locs;
+ context->c.mc = m;
+ FIRST (context).ptoken = first;
+ LAST (context).ptoken = first + count;
+}
+
/* Push a traditional macro's replacement text. */
void
_cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
@@ -1138,14 +1835,200 @@ _cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
{
cpp_context *context = next_context (pfile);
- context->direct_p = true;
- context->macro = macro;
+ context->tokens_kind = TOKENS_KIND_DIRECT;
+ context->c.macro = macro;
context->buff = NULL;
CUR (context) = start;
RLIMIT (context) = start + len;
macro->flags |= NODE_DISABLED;
}
+/* Creates a buffer that holds tokens a.k.a "token buffer", usually
+ for the purpose of storing them on a cpp_context. If VIRT_LOCS is
+ non-null (which means that -ftrack-macro-expansion is on),
+ *VIRT_LOCS is set to a newly allocated buffer that is supposed to
+ hold the virtual locations of the tokens resulting from macro
+ expansion. */
+static _cpp_buff*
+tokens_buff_new (cpp_reader *pfile, size_t len,
+ source_location **virt_locs)
+{
+ size_t tokens_size = len * sizeof (cpp_token *);
+ size_t locs_size = len * sizeof (source_location);
+
+ if (virt_locs != NULL)
+ *virt_locs = XNEWVEC (source_location, locs_size);
+ return _cpp_get_buff (pfile, tokens_size);
+}
+
+/* Returns the number of tokens contained in a token buffer. The
+ buffer holds a set of cpp_token*. */
+static size_t
+tokens_buff_count (_cpp_buff *buff)
+{
+ return (BUFF_FRONT (buff) - buff->base) / sizeof (cpp_token *);
+}
+
+/* Return a pointer to the last token contained in the token buffer
+ BUFF. */
+static const cpp_token **
+tokens_buff_last_token_ptr (_cpp_buff *buff)
+{
+ return &((const cpp_token **) BUFF_FRONT (buff))[-1];
+}
+
+/* Remove the last token contained in the token buffer TOKENS_BUFF.
+ If VIRT_LOCS_BUFF is non-NULL, it should point at the buffer
+ containing the virtual locations of the tokens in TOKENS_BUFF; in
+ which case the function updates that buffer as well. */
+static inline void
+tokens_buff_remove_last_token (_cpp_buff *tokens_buff)
+
+{
+ if (BUFF_FRONT (tokens_buff) > tokens_buff->base)
+ BUFF_FRONT (tokens_buff) =
+ (unsigned char *) &((cpp_token **) BUFF_FRONT (tokens_buff))[-1];
+}
+
+/* Insert a token into the token buffer at the position pointed to by
+ DEST. Note that the buffer is not enlarged so the previous token
+ that was at *DEST is overwritten. VIRT_LOC_DEST, if non-null,
+ means -ftrack-macro-expansion is effect; it then points to where to
+ insert the virtual location of TOKEN. TOKEN is the token to
+ insert. VIRT_LOC is the virtual location of the token, i.e, the
+ location possibly encoding its locus accross macro expansion. If
+ TOKEN is an argument of a function-like macro (inside a macro
+ replacement list), PARM_DEF_LOC is the spelling location of the
+ macro parameter that TOKEN is replacing, in the replacement list of
+ the macro. If TOKEN is not an argument of a function-like macro or
+ if it doesn't come from a macro expansion, then VIRT_LOC can just
+ be set to the same value as PARM_DEF_LOC. If MAP is non null, it
+ means TOKEN comes from a macro expansion and MAP is the macro map
+ associated to the macro. MACRO_TOKEN_INDEX points to the index of
+ the token in the macro map; it is not considered if MAP is NULL.
+
+ Upon successful completion this function returns the a pointer to
+ the position of the token coming right after the insertion
+ point. */
+static inline const cpp_token **
+tokens_buff_put_token_to (const cpp_token **dest,
+ source_location *virt_loc_dest,
+ const cpp_token *token,
+ source_location virt_loc,
+ source_location parm_def_loc,
+ const struct line_map *map,
+ unsigned int macro_token_index)
+{
+ source_location macro_loc = virt_loc;
+ const cpp_token **result;
+
+ if (virt_loc_dest)
+ {
+ /* -ftrack-macro-expansion is on. */
+ if (map)
+ macro_loc = linemap_add_macro_token (map, macro_token_index,
+ virt_loc, parm_def_loc);
+ *virt_loc_dest = macro_loc;
+ }
+ *dest = token;
+ result = &dest[1];
+
+ return result;
+}
+
+/* Adds a token at the end of the tokens contained in BUFFER. Note
+ that this function doesn't enlarge BUFFER when the number of tokens
+ reaches BUFFER's size; it aborts in that situation.
+
+ TOKEN is the token to append. VIRT_LOC is the virtual location of
+ the token, i.e, the location possibly encoding its locus accross
+ macro expansion. If TOKEN is an argument of a function-like macro
+ (inside a macro replacement list), PARM_DEF_LOC is the location of
+ the macro parameter that TOKEN is replacing. If TOKEN doesn't come
+ from a macro expansion, then VIRT_LOC can just be set to the same
+ value as PARM_DEF_LOC. If MAP is non null, it means TOKEN comes
+ from a macro expansion and MAP is the macro map associated to the
+ macro. MACRO_TOKEN_INDEX points to the index of the token in the
+ macro map; It is not considered if MAP is NULL. If VIRT_LOCS is
+ non-null, it means -ftrack-macro-expansion is on; in which case
+ this function adds the virtual location DEF_LOC to the VIRT_LOCS
+ array, at the same index as the one of TOKEN in BUFFER. Upon
+ successful completion this function returns the a pointer to the
+ position of the token coming right after the insertion point. */
+static const cpp_token **
+tokens_buff_add_token (_cpp_buff *buffer,
+ source_location *virt_locs,
+ const cpp_token *token,
+ source_location virt_loc,
+ source_location parm_def_loc,
+ const struct line_map *map,
+ unsigned int macro_token_index)
+{
+ const cpp_token **result;
+ source_location *virt_loc_dest = NULL;
+ unsigned token_index =
+ (BUFF_FRONT (buffer) - buffer->base) / sizeof (cpp_token *);
+
+ /* Abort if we pass the end the buffer. */
+ if (BUFF_FRONT (buffer) > BUFF_LIMIT (buffer))
+ abort ();
+
+ if (virt_locs != NULL)
+ virt_loc_dest = &virt_locs[token_index];
+
+ result =
+ tokens_buff_put_token_to ((const cpp_token **) BUFF_FRONT (buffer),
+ virt_loc_dest, token, virt_loc, parm_def_loc,
+ map, macro_token_index);
+
+ BUFF_FRONT (buffer) = (unsigned char *) result;
+ return result;
+}
+
+/* Allocate space for the function-like macro argument ARG to store
+ the tokens resulting from the macro-expansion of the tokens that
+ make up ARG itself. That space is allocated in ARG->expanded and
+ needs to be freed using free. */
+static void
+alloc_expanded_arg_mem (cpp_reader *pfile, macro_arg *arg, size_t capacity)
+{
+#ifdef ENABLE_CHECKING
+ if (arg->expanded != NULL
+ || arg->expanded_virt_locs != NULL)
+ abort ();
+#endif
+ arg->expanded = XNEWVEC (const cpp_token *, capacity);
+ if (CPP_OPTION (pfile, track_macro_expansion))
+ arg->expanded_virt_locs = XNEWVEC (source_location, capacity);
+
+}
+
+/* If necessary, enlarge ARG->expanded to so that it can contain SIZE
+ tokens. */
+static void
+ensure_expanded_arg_room (cpp_reader *pfile, macro_arg *arg,
+ size_t size, size_t *expanded_capacity)
+{
+ if (size <= *expanded_capacity)
+ return;
+
+ size *= 2;
+
+ arg->expanded =
+ XRESIZEVEC (const cpp_token *, arg->expanded, size);
+ *expanded_capacity = size;
+
+ if (CPP_OPTION (pfile, track_macro_expansion))
+ {
+ if (arg->expanded_virt_locs == NULL)
+ arg->expanded_virt_locs = XNEWVEC (source_location, size);
+ else
+ arg->expanded_virt_locs = XRESIZEVEC (source_location,
+ arg->expanded_virt_locs,
+ size);
+ }
+}
+
/* Expand an argument ARG before replacing parameters in a
function-like macro. This works by pushing a context with the
argument's tokens, and then expanding that into a temporary buffer
@@ -1155,38 +2038,48 @@ _cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
static void
expand_arg (cpp_reader *pfile, macro_arg *arg)
{
- unsigned int capacity;
+ size_t capacity;
bool saved_warn_trad;
+ bool track_macro_exp_p = CPP_OPTION (pfile, track_macro_expansion);
- if (arg->count == 0)
+ if (arg->count == 0
+ || arg->expanded != NULL)
return;
/* Don't warn about funlike macros when pre-expanding. */
saved_warn_trad = CPP_WTRADITIONAL (pfile);
CPP_WTRADITIONAL (pfile) = 0;
- /* Loop, reading in the arguments. */
+ /* Loop, reading in the tokens of the argument. */
capacity = 256;
- arg->expanded = XNEWVEC (const cpp_token *, capacity);
+ alloc_expanded_arg_mem (pfile, arg, capacity);
+
+ if (track_macro_exp_p)
+ push_extended_tokens_context (pfile, NULL, NULL,
+ arg->virt_locs,
+ arg->first,
+ arg->count + 1);
+ else
+ push_ptoken_context (pfile, NULL, NULL,
+ arg->first, arg->count + 1);
- push_ptoken_context (pfile, NULL, NULL, arg->first, arg->count + 1);
for (;;)
{
const cpp_token *token;
+ source_location location;
- if (arg->expanded_count + 1 >= capacity)
- {
- capacity *= 2;
- arg->expanded = XRESIZEVEC (const cpp_token *, arg->expanded,
- capacity);
- }
+ ensure_expanded_arg_room (pfile, arg, arg->expanded_count + 1,
+ &capacity);
- token = cpp_get_token (pfile);
+ token = cpp_get_token_1 (pfile, &location);
if (token->type == CPP_EOF)
break;
- arg->expanded[arg->expanded_count++] = token;
+ set_arg_token (arg, token, location,
+ arg->expanded_count, MACRO_ARG_TOKEN_EXPANDED,
+ CPP_OPTION (pfile, track_macro_expansion));
+ arg->expanded_count++;
}
_cpp_pop_context (pfile);
@@ -1195,25 +2088,132 @@ expand_arg (cpp_reader *pfile, macro_arg *arg)
}
/* Pop the current context off the stack, re-enabling the macro if the
- context represented a macro's replacement list. The context
- structure is not freed so that we can re-use it later. */
+ context represented a macro's replacement list. Initially the
+ context structure was not freed so that we can re-use it later, but
+ now we do free it to reduce peak memory consumption. */
void
_cpp_pop_context (cpp_reader *pfile)
{
cpp_context *context = pfile->context;
- if (context->macro)
- context->macro->flags &= ~NODE_DISABLED;
+ if (context->c.macro)
+ {
+ cpp_hashnode *macro;
+ if (context->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ macro_context *mc = context->c.mc;
+ macro = mc->macro_node;
+ /* If context->buff is set, it means the life time of tokens
+ is bound to the life time of this context; so we must
+ free the tokens; that means we must free the virtual
+ locations of these tokens too. */
+ if (context->buff && mc->virt_locs)
+ {
+ free (mc->virt_locs);
+ mc->virt_locs = NULL;
+ }
+ free (mc);
+ context->c.mc = NULL;
+ }
+ else
+ macro = context->c.macro;
+
+ /* Beware that MACRO can be NULL in cases like when we are
+ called from expand_arg. In those cases, a dummy context with
+ tokens is pushed just for the purpose of walking them using
+ cpp_get_token_1. In that case, no 'macro' field is set into
+ the dummy context. */
+ if (macro != NULL)
+ macro->flags &= ~NODE_DISABLED;
+ }
if (context->buff)
- _cpp_release_buff (pfile, context->buff);
+ {
+ /* Decrease memory peak consumption by freeing the memory used
+ by the context. */
+ _cpp_free_buff (context->buff);
+ }
pfile->context = context->prev;
+ /* decrease peak memory consumption by feeing the context. */
+ pfile->context->next = NULL;
+ free (context);
}
-/* External routine to get a token. Also used nearly everywhere
- internally, except for places where we know we can safely call
- _cpp_lex_token directly, such as lexing a directive name.
+/* Return TRUE if we reached the end of the set of tokens stored in
+ CONTEXT, FALSE otherwise. */
+static inline bool
+reached_end_of_context (cpp_context *context)
+{
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
+ return FIRST (context).token == LAST (context).token;
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT
+ || context->tokens_kind == TOKENS_KIND_EXTENDED)
+ return FIRST (context).ptoken == LAST (context).ptoken;
+ else
+ abort ();
+}
+
+/* Consume the next token contained in the current context of PFILE,
+ and return it in *TOKEN. It's "full location" is returned in
+ *LOCATION. If -ftrack-macro-location is in effeect, fFull location"
+ means the location encoding the locus of the token accross macro
+ expansion; otherwise it's just is the "normal" location of the
+ token which (*TOKEN)->src_loc. */
+static inline void
+consume_next_token_from_context (cpp_reader *pfile,
+ const cpp_token ** token,
+ source_location *location)
+{
+ cpp_context *c = pfile->context;
+
+ if ((c)->tokens_kind == TOKENS_KIND_DIRECT)
+ {
+ *token = FIRST (c).token;
+ *location = (*token)->src_loc;
+ FIRST (c).token++;
+ }
+ else if ((c)->tokens_kind == TOKENS_KIND_INDIRECT)
+ {
+ *token = *FIRST (c).ptoken;
+ *location = (*token)->src_loc;
+ FIRST (c).ptoken++;
+ }
+ else if ((c)->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ macro_context *m = c->c.mc;
+ *token = *FIRST (c).ptoken;
+ if (m->virt_locs)
+ {
+ *location = *m->cur_virt_loc;
+ m->cur_virt_loc++;
+ }
+ else
+ *location = (*token)->src_loc;
+ FIRST (c).ptoken++;
+ }
+ else
+ abort ();
+}
+
+/* In the traditional mode of the preprocessor, if we are currently in
+ a directive, the location of a token must be the location of the
+ start of the directive line. This function returns the proper
+ location if we are in the traditional mode, and just returns
+ LOCATION otherwise. */
+
+static inline source_location
+maybe_adjust_loc_for_trad_cpp (cpp_reader *pfile, source_location location)
+{
+ if (CPP_OPTION (pfile, traditional))
+ {
+ if (pfile->state.in_directive)
+ return pfile->directive_line;
+ }
+ return location;
+}
+
+/* Routine to get a token as well as its location.
Macro expansions and directives are transparently handled,
including entering included files. Thus tokens are post-macro
@@ -1221,12 +2221,20 @@ _cpp_pop_context (cpp_reader *pfile)
see CPP_EOF only at EOF. Internal callers also see it when meeting
a directive inside a macro call, when at the end of a directive and
state.in_directive is still 1, and at the end of argument
- pre-expansion. */
-const cpp_token *
-cpp_get_token (cpp_reader *pfile)
+ pre-expansion.
+
+ LOC is an out parameter; *LOC is set to the location "as expected
+ by the user". Please read the comment of
+ cpp_get_token_with_location to learn more about the meaning of this
+ location. */
+static const cpp_token*
+cpp_get_token_1 (cpp_reader *pfile, source_location *location)
{
const cpp_token *result;
bool can_set = pfile->set_invocation_location;
+ /* This token is a virtual token that either encodes a location
+ related to macro expansion or a spelling location. */
+ source_location virt_loc = 0;
pfile->set_invocation_location = false;
for (;;)
@@ -1236,28 +2244,32 @@ cpp_get_token (cpp_reader *pfile)
/* Context->prev == 0 <=> base context. */
if (!context->prev)
- result = _cpp_lex_token (pfile);
- else if (FIRST (context).token != LAST (context).token)
{
- if (context->direct_p)
- result = FIRST (context).token++;
- else
- result = *FIRST (context).ptoken++;
-
+ result = _cpp_lex_token (pfile);
+ virt_loc = result->src_loc;
+ }
+ else if (!reached_end_of_context (context))
+ {
+ consume_next_token_from_context (pfile, &result,
+ &virt_loc);
if (result->flags & PASTE_LEFT)
{
paste_all_tokens (pfile, result);
if (pfile->state.in_directive)
continue;
- return padding_token (pfile, result);
+ result = padding_token (pfile, result);
+ goto out;
}
}
else
{
+ if (pfile->context->c.macro)
+ ++num_expanded_macros_counter;
_cpp_pop_context (pfile);
if (pfile->state.in_directive)
continue;
- return &pfile->avoid_paste;
+ result = &pfile->avoid_paste;
+ goto out;
}
if (pfile->state.in_directive && result->type == CPP_COMMENT)
@@ -1276,7 +2288,7 @@ cpp_get_token (cpp_reader *pfile)
int ret = 0;
/* If not in a macro context, and we're going to start an
expansion, record the location. */
- if (can_set && !context->macro)
+ if (can_set && !context->c.macro)
pfile->invocation_location = result->src_loc;
if (pfile->state.prevent_expansion)
break;
@@ -1294,7 +2306,8 @@ cpp_get_token (cpp_reader *pfile)
|| (peek_tok->flags & PREV_WHITE));
node = pfile->cb.macro_to_expand (pfile, result);
if (node)
- ret = enter_macro_context (pfile, node, result);
+ ret = enter_macro_context (pfile, node, result,
+ virt_loc);
else if (whitespace_after)
{
/* If macro_to_expand hook returned NULL and it
@@ -1311,12 +2324,14 @@ cpp_get_token (cpp_reader *pfile)
}
}
else
- ret = enter_macro_context (pfile, node, result);
+ ret = enter_macro_context (pfile, node, result,
+ virt_loc);
if (ret)
{
if (pfile->state.in_directive || ret == 2)
continue;
- return padding_token (pfile, result);
+ result = padding_token (pfile, result);
+ goto out;
}
}
else
@@ -1333,27 +2348,88 @@ cpp_get_token (cpp_reader *pfile)
break;
}
+ out:
+ if (location != NULL)
+ {
+ if (virt_loc == 0)
+ virt_loc = result->src_loc;
+ *location = virt_loc;
+
+ if (!CPP_OPTION (pfile, track_macro_expansion)
+ && can_set
+ && pfile->context->c.macro != NULL)
+ /* We are in a macro expansion context, are not tracking
+ virtual location, but were asked to report the location
+ of the expansion point of the macro being expanded. */
+ *location = pfile->invocation_location;
+
+ *location = maybe_adjust_loc_for_trad_cpp (pfile, *location);
+ }
return result;
}
-/* Like cpp_get_token, but also returns a location separate from the
- one provided by the returned token. LOC is an out parameter; *LOC
- is set to the location "as expected by the user". This matters
- when a token results from macro expansion -- the token's location
- will indicate where the macro is defined, but *LOC will be the
- location of the start of the expansion. */
+/* External routine to get a token. Also used nearly everywhere
+ internally, except for places where we know we can safely call
+ _cpp_lex_token directly, such as lexing a directive name.
+
+ Macro expansions and directives are transparently handled,
+ including entering included files. Thus tokens are post-macro
+ expansion, and after any intervening directives. External callers
+ see CPP_EOF only at EOF. Internal callers also see it when meeting
+ a directive inside a macro call, when at the end of a directive and
+ state.in_directive is still 1, and at the end of argument
+ pre-expansion. */
+const cpp_token *
+cpp_get_token (cpp_reader *pfile)
+{
+ return cpp_get_token_1 (pfile, NULL);
+}
+
+/* Like cpp_get_token, but also returns a virtual token location
+ separate from the spelling location carried by the returned token.
+
+ LOC is an out parameter; *LOC is set to the location "as expected
+ by the user". This matters when a token results from macro
+ expansion; in that case the token's spelling location indicates the
+ locus of the token in the definition of the macro but *LOC
+ virtually encodes all the other meaningful locuses associated to
+ the token.
+
+ What? virtual location? Yes, virtual location.
+
+ If the token results from macro expansion and if macro expansion
+ location tracking is enabled its virtual location encodes (at the
+ same time):
+
+ - the spelling location of the token
+
+ - the locus of the macro expansion point
+
+ - the locus of the point where the token got instantiated as part
+ of the macro expansion process.
+
+ You have to use the linemap API to get the locus you are interested
+ in from a given virtual location.
+
+ Note however that virtual locations are not necessarily ordered for
+ relations '<' and '>'. One must use the function
+ linemap_location_before_p instead of using the relational operator
+ '<'.
+
+ If macro expansion tracking is off and if the token results from
+ macro expansion the virtual location is the expansion point of the
+ macro that got expanded.
+
+ When the token doesn't result from macro expansion, the virtual
+ location is just the same thing as its spelling location. */
+
const cpp_token *
cpp_get_token_with_location (cpp_reader *pfile, source_location *loc)
{
const cpp_token *result;
pfile->set_invocation_location = true;
- result = cpp_get_token (pfile);
- if (pfile->context->macro)
- *loc = pfile->invocation_location;
- else
- *loc = result->src_loc;
-
+ result = cpp_get_token_1 (pfile, loc);
return result;
}
@@ -1363,7 +2439,7 @@ cpp_get_token_with_location (cpp_reader *pfile, source_location *loc)
int
cpp_sys_macro_p (cpp_reader *pfile)
{
- cpp_hashnode *node = pfile->context->macro;
+ cpp_hashnode *node = pfile->context->c.macro;
return node && node->value.macro && node->value.macro->syshdr;
}
@@ -1420,10 +2496,27 @@ _cpp_backup_tokens (cpp_reader *pfile, unsigned int count)
{
if (count != 1)
abort ();
- if (pfile->context->direct_p)
+ if (pfile->context->tokens_kind == TOKENS_KIND_DIRECT)
FIRST (pfile->context).token--;
- else
+ else if (pfile->context->tokens_kind == TOKENS_KIND_INDIRECT)
FIRST (pfile->context).ptoken--;
+ else if (pfile->context->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ FIRST (pfile->context).ptoken--;
+ if (pfile->context->c.macro)
+ {
+ macro_context *m = pfile->context->c.mc;
+ m->cur_virt_loc--;
+#ifdef ENABLE_CHECKING
+ if (m->cur_virt_loc < m->virt_locs)
+ abort ();
+#endif
+ }
+ else
+ abort ();
+ }
+ else
+ abort ();
}
}
diff --git a/libcpp/traditional.c b/libcpp/traditional.c
index 7ff11bb205e..4206b6fa768 100644
--- a/libcpp/traditional.c
+++ b/libcpp/traditional.c
@@ -738,7 +738,7 @@ recursive_macro (cpp_reader *pfile, cpp_hashnode *node)
do
{
depth++;
- if (context->macro == node && depth > 20)
+ if (context->c.macro == node && depth > 20)
break;
context = context->prev;
}
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index a9f771c82ec..54287b40b19 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,27 @@
+2011-10-16 Uros Bizjak <ubizjak@gmail.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50737
+ * config/alpha/linux-unwind.h (alpha_fallback_frame_state): Set
+ fs->signal_frame to 1.
+
+2011-10-07 Ian Lance Taylor <iant@google.com>
+
+ * generic-morestack-thread.c: #include <errno.h>.
+
+2011-10-07 Ian Lance Taylor <iant@google.com>
+
+ PR target/46093
+ * generic-morestack.c (__generic_morestack): Make sure the segment
+ is large enough for both the stack frame and the copied
+ parameters.
+
+2011-10-06 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR bootstrap/49804
+ * config.host: Add crtbegin.o, crtbeginS.o, crtend.o, crtendS.o to
+ extra_parts.
+
2011-09-28 Nick Clifton <nickc@redhat.com>
* config/rx/rx-lib.h: Always restrict doubles to the SF type when
diff --git a/libgcc/config.host b/libgcc/config.host
index 25afb378db2..08c00a37f97 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -777,7 +777,7 @@ sparc-wrs-vxworks)
;;
sparc64-*-freebsd*|ultrasparc-*-freebsd*)
tmake_file="$tmake_file t-crtfm"
- extra_parts=crtfastmath.o
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o crtfastmath.o"
;;
sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux
extra_parts="$extra_parts crtfastmath.o"
diff --git a/libgcc/config/alpha/linux-unwind.h b/libgcc/config/alpha/linux-unwind.h
index e43aacfd00b..629d557c46c 100644
--- a/libgcc/config/alpha/linux-unwind.h
+++ b/libgcc/config/alpha/linux-unwind.h
@@ -74,5 +74,7 @@ alpha_fallback_frame_state (struct _Unwind_Context *context,
fs->regs.reg[64].how = REG_SAVED_OFFSET;
fs->regs.reg[64].loc.offset = (long)&sc->sc_pc - new_cfa;
fs->retaddr_column = 64;
+ fs->signal_frame = 1;
+
return _URC_NO_REASON;
}
diff --git a/libgcc/generic-morestack-thread.c b/libgcc/generic-morestack-thread.c
index bc237957ef6..794fdc3dc54 100644
--- a/libgcc/generic-morestack-thread.c
+++ b/libgcc/generic-morestack-thread.c
@@ -1,5 +1,5 @@
/* Thread library support for -fsplit-stack. */
-/* Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
Contributed by Ian Lance Taylor <iant@google.com>.
This file is part of GCC.
@@ -36,6 +36,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef inhibit_libc
+#include <errno.h>
#include <pthread.h>
#include "generic-morestack.h"
diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c
index 7e29bbcf748..0b660cedd5f 100644
--- a/libgcc/generic-morestack.c
+++ b/libgcc/generic-morestack.c
@@ -512,7 +512,7 @@ __generic_morestack (size_t *pframe_size, void *old_stack, size_t param_size)
current = *pp;
if (current == NULL)
- current = allocate_segment (frame_size);
+ current = allocate_segment (frame_size + param_size);
current->old_stack = old_stack;
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 37864682ea1..6858636c1ab 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,7 @@
+2011-10-10 Matthias Klose <doko@ubuntu.com>
+
+ * config/posix95: Remove empty directory.
+
2011-08-26 Jakub Jelinek <jakub@redhat.com>
* testsuite/libgomp.fortran/threadprivate4.f90: New test.
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 59460e43f09..6859afa04c3 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,10 @@
+2011-10-10 Ian Lance Taylor <iant@google.com>
+
+ PR c++/48665
+ * cp-demangle.c (d_cv_qualifiers): If qualifiers are applied to a
+ function type, change them to apply to the "this" parameter.
+ * testsuite/demangle-expected: Add test case.
+
2011-09-28 Doug Evans <dje@google.com>
* timeval-utils.c: New file.
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 32318e89fd8..c7afef01f6d 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -2294,8 +2294,10 @@ static struct demangle_component **
d_cv_qualifiers (struct d_info *di,
struct demangle_component **pret, int member_fn)
{
+ struct demangle_component **pstart;
char peek;
+ pstart = pret;
peek = d_peek_char (di);
while (peek == 'r' || peek == 'V' || peek == 'K')
{
@@ -2332,6 +2334,28 @@ d_cv_qualifiers (struct d_info *di,
peek = d_peek_char (di);
}
+ if (!member_fn && peek == 'F')
+ {
+ while (pstart != pret)
+ {
+ switch ((*pstart)->type)
+ {
+ case DEMANGLE_COMPONENT_RESTRICT:
+ (*pstart)->type = DEMANGLE_COMPONENT_RESTRICT_THIS;
+ break;
+ case DEMANGLE_COMPONENT_VOLATILE:
+ (*pstart)->type = DEMANGLE_COMPONENT_VOLATILE_THIS;
+ break;
+ case DEMANGLE_COMPONENT_CONST:
+ (*pstart)->type = DEMANGLE_COMPONENT_CONST_THIS;
+ break;
+ default:
+ break;
+ }
+ pstart = &d_left (*pstart);
+ }
+ }
+
return pret;
}
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 64ccb929680..70abf681ae8 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4198,3 +4198,8 @@ f1<int>
_Z3fooi._omp_cpyfn.6
foo(int) [clone ._omp_cpyfn.6]
foo
+#
+--format=gnu-v3 --no-params
+_Z1fIKFvvES0_Evv
+void f<void () const, void ()>()
+f<void () const, void ()>
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 53adfd45285..efbf85573ff 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,10 @@
+2011-10-16 Uros Bizjak <ubizjak@gmail.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50737
+ * include/dwarf2-signal.h [__alpha__]: Remove MAKE_THROW_FRAME
+ definition.
+
2011-08-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* exception.cc (std::abort): Remove static.
diff --git a/libjava/include/dwarf2-signal.h b/libjava/include/dwarf2-signal.h
index 949bcc0ae39..812968217ee 100644
--- a/libjava/include/dwarf2-signal.h
+++ b/libjava/include/dwarf2-signal.h
@@ -29,20 +29,7 @@ class java::lang::Throwable;
// then throw an exception. With the dwarf2 unwinder we don't usually
// need to do anything, with some minor exceptions.
-#ifdef __alpha__
-#define MAKE_THROW_FRAME(_exception) \
-do \
-{ \
- /* Alpha either leaves PC pointing at a faulting instruction or the \
- following instruction, depending on the signal. SEGV always does \
- the former, so we adjust the saved PC to point to the following \
- instruction; this is what the handler in libgcc expects. */ \
- struct sigcontext *_sc = (struct sigcontext *)_p; \
- _sc->sc_pc += 4; \
-} \
-while (0)
-
-#elif defined(__ia64__)
+#ifdef __ia64__
#define MAKE_THROW_FRAME(_exception) \
do \
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index b9f87fabec9..dbc70f190bb 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,29 @@
+2011-10-09 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ PR libobjc/49883
+ * init.c (__objc_exec_class): Work around a bug in clang's code
+ generation. Clang sets the class->info field to values different
+ from 0x1 or 0x2 (the only allowed values in the traditional GNU
+ Objective-C runtime ABI) to store some additional information, but
+ this breaks backwards compatibility. Wipe out all the bits in the
+ fields other than the first two upon loading a class.
+
+2011-10-09 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * class.c (objc_lookup_class): Added back for compatibility with
+ clang which seems to emit calls to it.
+
+2011-10-08 Richard Frith-Macdonald <rfm@gnu.org>
+ Nicola Pero <nicola.pero@meta-innovation.com>
+
+ PR libobjc/50428
+ * sendmsg.c (__objc_send_initialize): If a class does not have an
+ +initialize method, search for an +initialize method in the
+ superclass and in the ancestor classes and execute the first one
+ that is found. This makes the GNU runtime behave in the same way
+ as the Apple/NeXT runtime with respect to +initialize methods and
+ subclassing.
+
2011-08-06 Nicola Pero <nicola.pero@meta-innovation.com>
PR libobjc/50002
diff --git a/libobjc/class.c b/libobjc/class.c
index edc56aa9ec4..3b750829f3b 100644
--- a/libobjc/class.c
+++ b/libobjc/class.c
@@ -764,6 +764,15 @@ objc_get_meta_class (const char *name)
return objc_get_class (name)->class_pointer;
}
+/* This is not used by GCC, but the clang compiler seems to use it
+ when targetting the GNU runtime. That's wrong, but we have it to
+ be compatible. */
+Class
+objc_lookup_class (const char *name)
+{
+ return objc_getClass (name);
+}
+
/* This is used when the implementation of a method changes. It goes
through all classes, looking for the ones that have these methods
(either method_a or method_b; method_b can be NULL), and reloads
diff --git a/libobjc/init.c b/libobjc/init.c
index d4475b3b787..23ba41ba128 100644
--- a/libobjc/init.c
+++ b/libobjc/init.c
@@ -643,6 +643,15 @@ __objc_exec_class (struct objc_module *module)
assert (CLS_ISMETA (class->class_pointer));
DEBUG_PRINTF (" installing class '%s'\n", class->name);
+ /* Workaround for a bug in clang: Clang may set flags other than
+ _CLS_CLASS and _CLS_META even when compiling for the
+ traditional ABI (version 8), confusing our runtime. Try to
+ wipe these flags out. */
+ if (CLS_ISCLASS (class))
+ __CLS_INFO (class) = _CLS_CLASS;
+ else
+ __CLS_INFO (class) = _CLS_META;
+
/* Initialize the subclass list to be NULL. In some cases it
isn't and this crashes the program. */
class->subclass_list = NULL;
diff --git a/libobjc/sendmsg.c b/libobjc/sendmsg.c
index 8aa266dd11f..ea8ea970262 100644
--- a/libobjc/sendmsg.c
+++ b/libobjc/sendmsg.c
@@ -516,34 +516,13 @@ __objc_send_initialize (Class class)
{
SEL op = sel_registerName ("initialize");
- IMP imp = 0;
- struct objc_method_list * method_list = class->class_pointer->methods;
-
- while (method_list)
- {
- int i;
- struct objc_method * method;
-
- for (i = 0; i < method_list->method_count; i++)
- {
- method = &(method_list->method_list[i]);
- if (method->method_name
- && method->method_name->sel_id == op->sel_id)
- {
- imp = method->method_imp;
- break;
- }
- }
-
- if (imp)
- break;
-
- method_list = method_list->method_next;
- }
- if (imp)
+ struct objc_method *method = search_for_method_in_hierarchy (class->class_pointer,
+ op);
+
+ if (method)
{
DEBUG_PRINTF (" begin of [%s +initialize]\n", class->name);
- (*imp) ((id) class, op);
+ (*method->method_imp) ((id)class, op);
DEBUG_PRINTF (" end of [%s +initialize]\n", class->name);
}
#ifdef DEBUG
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index a03f1afe033..9f70e377e77 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,202 @@
+2011-10-19 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ * include/tr2/bool_set (bool_set): New.
+ * include/tr2/bool_set.tcc: New.
+ * include/tr2/dynamic_bitset (dynamic_bitset): New.
+ * include/tr2/ratio (kibi, mebi, gibi, tebi, pebi, exbi): New.
+ * include/Makefile.am: Add files.
+ * include/Makefile.in: Regenerate.
+
+2011-10-19 Benjamin Kosnik <bkoz@redhat.com>
+
+ * doc/doxygen/user.cfg.in: Add tr2 files.
+ * testsuite/tr2/headers/all.cc: New.
+ * testsuite/tr2/headers/using_namespace_std_tr2.cc: New.
+
+ * include/tr2/type_traits: Tweak.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50500
+ * include/bits/shared_ptr.h: Default copy ctor and assignment.
+ * testsuite/util/testsuite_allocator.h: Define copy assignment.
+ * testsuite/util/testsuite_rvalref.h: Default copy assignment.
+ * testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Remove note tags.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * include/tr2/type_traits (bases, direct_bases, typelist): New.
+
+2011-10-17 Benjamin Kosnik <bkoz@redhat.com>
+
+ * libstdc++-v3/include/Makefile.am: Add tr2 directory and includes.
+ * libstdc++-v3/include/Makefile.in: Regenerate.
+
+ * scripts/create_testsuite_files: Search tr2 directory.
+ * testsuite/libstdc++-dg/conformance.exp: Same.
+
+ * testsuite/tr2/bases/requirements/explicit_instantiation.cc: New.
+ * testsuite/tr2/bases/requirements/typedefs.cc: New.
+ * testsuite/tr2/bases/value.cc: New.
+ * testsuite/tr2/direct_bases/requirements/
+ explicit_instantiation.cc: New.
+ * testsuite/tr2/direct_bases/requirements/typedefs.cc: New.
+ * testsuite/tr2/direct_bases/value.cc: New.
+
+2011-10-17 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR bootstrap/50715
+ * config/abi/pre/gnu.ver (CXXABI_1.3.6): Remove duplicate
+ __cxa_get_exception_ptr.
+
+2011-10-14 François Dumont <francois.cppdevs@free.fr>
+
+ * testsuite/performance/23_containers/insert_erase/41975.cc: New.
+
+2011-10-14 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/22_locale/codecvt_byname/50714.cc: Fix mychar.
+
+2011-10-14 Jonathan Yong <jon_y@users.sourceforge.net>
+
+ * configure.host: Use config/os/mingw32-w64 instead of
+ config/os/mingw32 if vendor key is "w64".
+ * config/os/mingw32-w64: Duplicate from config/os/mingw32.
+ * config/os/mingw32-w64/os_defines.h: Enable
+ _GLIBCXX_FULLY_DYNAMIC_STRING if undefined.
+ * acinclude.m4: Set fully-dynamic-string to 1 when enabled,
+ 0 when disabled or undefined if unset by user.
+ * include/bits/basic_string.h: Check if
+ _GLIBCXX_FULLY_DYNAMIC_STRING is set to 0 instead of undefined.
+ include/bits/basic_string.tcc: Likewise.
+ * configure: Regenerated.
+ * config.h.in: Likewise.
+
+2011-10-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/50714
+ * include/bits/codecvt.h (codecvt<>::codecvt(size_t)): Initialize
+ _M_c_locale_codecvt member.
+ * testsuite/22_locale/codecvt_byname/50714.cc: New.
+
+2011-10-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50594
+ * libsupc++/new (operator new, operator delete): Decorate with
+ __attribute__((__externally_visible__)).
+ * include/bits/c++config: Add _GLIBCXX_THROW.
+ * libsupc++/del_op.cc: Adjust.
+ * libsupc++/del_opv.cc: Likewise.
+ * libsupc++/del_opnt.cc: Likewise.
+ * libsupc++/del_opvnt.cc: Likewise.
+ * libsupc++/new_op.cc: Likewise.
+ * libsupc++/new_opv.cc: Likewise.
+ * libsupc++/new_opnt.cc: Likewise.
+ * libsupc++/new_opvnt.cc: Likewise.
+ * testsuite/18_support/50594.cc: New.
+ * testsuite/ext/profile/mutex_extensions_neg.cc: Adjust dg-error
+ line number.
+
+2011-10-11 Emil Wojak <emil@wojak.eu>
+
+ PR c++/50661
+ * include/bits/stl_algobase.h (equal): Compare arrays of pointers
+ too with memcmp.
+
+2011-10-10 Benjamin Kosnik <bkoz@redhat.com>
+
+ PR libstdc++/49818
+ * config/abi/pre/gnu.ver (CXXABI_1.3.6): Add symbols.
+ * testsuite/util/testsuite_abi.cc: Same.
+ * libsupc++/unwind-cxx.h: Move required eh API...
+ * libsupc++/cxxabi.h: ... to here. Add required forward declarations.
+ Use _GLIBCXX_NOTHROW.
+ * libsupc++/pure.cc (__cxa_deleted_virtual): Add.
+ * libsupc++/eh_alloc.cc: Use _GLIBCXX_NOTHROW.
+ * libsupc++/eh_catch.cc: Same.
+ * libsupc++/eh_globals.cc: Same.
+ * libsupc++/eh_type.cc: Same.
+
+2011-10-07 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/util/testsuite_allocator.h (uneq_allocator): Add
+ propagate_on_container_swap typedef for C++0x testing.
+
+2011-10-06 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/27_io/ios_base/cons/assign_neg.cc: Tidy dg- directives,
+ for C++0x testing too.
+ * testsuite/27_io/ios_base/cons/copy_neg.cc: Likewise.
+ * testsuite/ext/pb_ds/example/hash_resize_neg.cc: Likewise.
+ * testsuite/24_iterators/istreambuf_iterator/requirements/
+ base_classes.cc: Adjust for C++0x testing.
+ * testsuite/ext/codecvt/char-1.cc: Avoid warnings in C++0x mode.
+ * testsuite/ext/codecvt/char-2.cc: Likewise.
+ * testsuite/ext/codecvt/wchar_t.cc: Likewise.
+
+2011-10-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/ext/pod_char_traits.h: Avoid warnings in C++0x mode
+ when int_type is unsigned.
+
+2011-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/49561
+ * include/bits/stl_list.h (_List_base<>::_List_impl::_M_size):
+ Add in C++0x mode.
+ (_List_base<>::_List_impl, _List_base<>::_M_get_node,
+ _List_base<>::_M_put_node, _List_base<>::_List_base(_List_base&&),
+ list<>::size, list<>::swap, list<>::splice): Use it.
+ (operator==(const list<>&, const list<>&)): Rewrite in C++0x mode.
+ * include/bits/list.tcc (list<>::erase): Likewise.
+ (list<>::merge): Adjust in C++0x mode.
+ * testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
+ Adjust dg-error line number.
+ * testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
+ Likewise.
+ * testsuite/23_containers/list/requirements/dr438/
+ constructor_1_neg.cc: Likewise.
+ * testsuite/23_containers/list/requirements/dr438/
+ constructor_2_neg.cc: Likewise.
+
+2011-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/20_util/bind/48698.cc (g): Fix return type, avoid -Wall
+ warning.
+
+2011-10-04 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/ext/alloc_traits.h (__alloc_traits::max_size): Define.
+ (__alloc_traits::rebind): Define.
+ * include/bits/stl_vector.h: Use them.
+ * testsuite/util/testsuite_allocator.h (SimpleAllocator): Define.
+ * testsuite/23_containers/vector/allocator/minimal.cc: New.
+ * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
+ Adjust dg-error line numbers.
+ * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
+ Likewise.
+ * testsuite/23_containers/vector/requirements/dr438/
+ constructor_1_neg.cc: Likewise.
+ * testsuite/23_containers/vector/requirements/dr438/
+ constructor_2_neg.cc: Likewise.
+
+2011-10-03 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/20_util/pointer_traits/pointer_to.cc: Define equality
+ operator and use.
+
+2011-10-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/bits/hashtable.h (_Hashtable<>::insert(value_type&&),
+ insert(const_iterator, value_type&&)): Don't define here...
+ * include/bits/unordered_set.h (__unordered_set<>,
+ __unordered_multiset<>): ... define here instead.
+
+2011-09-29 Jason Merrill <jason@redhat.com>
+
+ * testsuite/util/testsuite_tr1.h (test_property): Avoid
+ ambiguity.
+
2011-10-01 François Dumont <fdumont@gcc.gnu.org>
* include/debug/vector (vector<>::erase(iterator, iterator): Check
@@ -40,7 +239,7 @@
* testsuite/23_containers/deque/modifiers/erase/3.cc: Adjust.
2011-09-25 Benjamin Kosnik <bkoz@redhat.com>
- Jonathan Wakely <jwakely.gcc@gmail.com>
+ Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/48698
* acinclude.m4 (GLIBCXX_ENABLE_SYMVERS): Set libtool_VERSION here.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 1b9d025efc3..7196acfc374 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -564,17 +564,21 @@ dnl be turned on, that does not put empty objects in per-process static
dnl memory (mostly useful together with shared memory allocators, see PR
dnl libstdc++/16612 for details).
dnl
-dnl --enable-fully-dynamic-string defines _GLIBCXX_FULLY_DYNAMIC_STRING
-dnl --disable-fully-dynamic-string leaves _GLIBCXX_FULLY_DYNAMIC_STRING undefined
+dnl --enable-fully-dynamic-string defines _GLIBCXX_FULLY_DYNAMIC_STRING to 1
+dnl --disable-fully-dynamic-string defines _GLIBCXX_FULLY_DYNAMIC_STRING to 0
+dnl otherwise undefined
dnl + Usage: GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING[(DEFAULT)]
dnl Where DEFAULT is either `yes' or `no'.
dnl
AC_DEFUN([GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING], [
GLIBCXX_ENABLE(fully-dynamic-string,$1,,[do not put empty strings in per-process static memory])
if test $enable_fully_dynamic_string = yes; then
- AC_DEFINE(_GLIBCXX_FULLY_DYNAMIC_STRING, 1,
- [Define if a fully dynamic basic_string is wanted.])
+ enable_fully_dynamic_string_def=1
+ else
+ enable_fully_dynamic_string_def=0
fi
+ AC_DEFINE_UNQUOTED([_GLIBCXX_FULLY_DYNAMIC_STRING], [${enable_fully_dynamic_string_def}],
+ [Define to 1 if a fully dynamic basic_string is wanted, 0 to disable, undefined for platform defaults])
])
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 82470c8cec9..df7effb6a6b 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -707,7 +707,8 @@
/* Define to use concept checking code from the boost libraries. */
#undef _GLIBCXX_CONCEPT_CHECKS
-/* Define if a fully dynamic basic_string is wanted. */
+/* Define to 1 if a fully dynamic basic_string is wanted, 0 to disable,
+ undefined for platform defaults */
#undef _GLIBCXX_FULLY_DYNAMIC_STRING
/* Define if gthreads library is available. */
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 5e5aa6a5810..bb5ff9a3a20 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -104,7 +104,7 @@ GLIBCXX_3.4 {
std::logic_error*;
std::locale::[A-Za-e]*;
std::locale::facet::[A-Za-z]*;
- std::locale::facet::_S_get_c_locale*;
+ std::locale::facet::_S_get_c_locale*;
std::locale::facet::_S_clone_c_locale*;
std::locale::facet::_S_create_c_locale*;
std::locale::facet::_S_destroy_c_locale*;
@@ -145,7 +145,7 @@ GLIBCXX_3.4 {
std::strstream*;
std::strstreambuf*;
# std::t[a-q]*;
- std::t[a-g]*;
+ std::t[a-g]*;
std::th[a-h]*;
std::th[j-q]*;
std::th[s-z]*;
@@ -238,7 +238,7 @@ GLIBCXX_3.4 {
_ZNKSs8_M_limit*;
_ZNKSs9_M_ibeginEv;
_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_E*;
- _ZNKSs7compare*;
+ _ZNKSs7compare*;
_ZNKSs5c_strEv;
_ZNKSs8capacityEv;
_ZNKSs4copyEPc[jmy][jmy];
@@ -435,10 +435,10 @@ GLIBCXX_3.4 {
# std::locale destructors
_ZNSt6localeD*;
-
+
# std::locale::facet destructors
_ZNSt6locale5facetD*;
-
+
# std::locale::_Impl constructors, destructors
_ZNSt6locale5_ImplC*;
_ZNSt6locale5_ImplD*;
@@ -447,7 +447,7 @@ GLIBCXX_3.4 {
_ZNSt8ios_baseD*;
_ZNSt8ios_base4InitD*;
- # bool std::has_facet
+ # bool std::has_facet
_ZSt9has_facetIS*;
# std::use_facet
@@ -486,7 +486,7 @@ GLIBCXX_3.4 {
# std::time_get_byname
_ZNSt15time_get_byname*;
-
+
# std::time_put
_ZNSt8time_put*;
_ZNKSt8time_put*;
@@ -569,7 +569,7 @@ GLIBCXX_3.4 {
_ZNK11__gnu_debug16_Error_formatter13_M_print_word*;
_ZNK11__gnu_debug16_Error_formatter15_M_print_string*;
_ZNK11__gnu_debug16_Error_formatter8_M_error*;
-
+
# exceptions as functions
_ZSt16__throw_bad_castv;
_ZSt17__throw_bad_allocv;
@@ -809,11 +809,11 @@ GLIBCXX_3.4 {
};
GLIBCXX_3.4.1 {
-
+
_ZNSt12__basic_fileIcE4fileEv;
-
+
} GLIBCXX_3.4;
-
+
GLIBCXX_3.4.2 {
_ZN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EE4fileEv;
@@ -825,7 +825,7 @@ GLIBCXX_3.4.2 {
} GLIBCXX_3.4.1;
GLIBCXX_3.4.3 {
-
+
# stub functions from libmath
acosf;
acosl;
@@ -969,7 +969,7 @@ GLIBCXX_3.4.10 {
_ZNKSt4hashIeEclEe;
_ZSt17__verify_grouping*;
-
+
_ZNSt8__detail12__prime_listE;
_ZNSt3tr18__detail12__prime_listE;
@@ -992,7 +992,7 @@ GLIBCXX_3.4.10 {
} GLIBCXX_3.4.9;
GLIBCXX_3.4.11 {
-
+
# atomic
__atomic_flag_for_address;
__atomic_flag_wait_explicit;
@@ -1328,16 +1328,16 @@ CXXABI_1.3 {
__cxa_rethrow;
__cxa_throw;
__cxa_type_match;
+ __cxa_vec_ctor;
__cxa_vec_cctor;
__cxa_vec_cleanup;
- __cxa_vec_ctor;
+ __cxa_vec_delete;
__cxa_vec_delete2;
__cxa_vec_delete3;
- __cxa_vec_delete;
__cxa_vec_dtor;
+ __cxa_vec_new;
__cxa_vec_new2;
__cxa_vec_new3;
- __cxa_vec_new;
__gxx_personality_v0;
__gxx_personality_sj0;
__dynamic_cast;
@@ -1491,3 +1491,11 @@ CXXABI_1.3.5 {
_ZTVSt16nested_exception;
} CXXABI_1.3.4;
+
+CXXABI_1.3.6 {
+
+ __cxa_allocate_dependent_exception;
+ __cxa_free_dependent_exception;
+ __cxa_deleted_virtual;
+
+} CXXABI_1.3.5;
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_base.h b/libstdc++-v3/config/os/mingw32-w64/ctype_base.h
new file mode 100644
index 00000000000..5fbdff8e7f0
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_base.h
@@ -0,0 +1,64 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 1997, 1998, 1999, 2007, 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+// We don't use the C-locale masks defined in mingw/include/ctype.h
+// because those masks do not conform to the requirements of 22.2.1.
+// In particular, a separate 'print' bitmask does not exist (isprint(c)
+// relies on a combination of flags) and the '_ALPHA' mask is also a
+// combination of simple bitmasks. Thus, we define libstdc++-specific
+// masks here, based on the generic masks, and the corresponding
+// classic_table in ctype_noninline.h.
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /// @brief Base class for ctype.
+ struct ctype_base
+ {
+ // Non-standard typedefs.
+ typedef const int* __to_type;
+
+ // NB: Offsets into ctype<char>::_M_table force a particular size
+ // on the mask type. Because of this, we don't use an enum.
+ typedef unsigned short mask;
+ static const mask upper = 1 << 0;
+ static const mask lower = 1 << 1;
+ static const mask alpha = 1 << 2;
+ static const mask digit = 1 << 3;
+ static const mask xdigit = 1 << 4;
+ static const mask space = 1 << 5;
+ static const mask print = 1 << 6;
+ static const mask graph = (1 << 2) | (1 << 3) | (1 << 9); // alnum|punct
+ static const mask cntrl = 1 << 8;
+ static const mask punct = 1 << 9;
+ static const mask alnum = (1 << 2) | (1 << 3); // alpha|digit
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc b/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc
new file mode 100644
index 00000000000..12184075d77
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc
@@ -0,0 +1,243 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file ctype_configure_char.cc */
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+#include <locale>
+#include <cstdlib>
+#include <cstring>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // The classic table used in libstdc++ is *not* the C _ctype table
+ // used by mscvrt, but is based on the ctype masks defined for libstdc++
+ // in ctype_base.h.
+
+ const ctype_base::mask*
+ ctype<char>::classic_table() throw()
+ {
+ static const ctype_base::mask _S_classic_table[256] =
+ {
+ cntrl /* null */,
+ cntrl /* ^A */,
+ cntrl /* ^B */,
+ cntrl /* ^C */,
+ cntrl /* ^D */,
+ cntrl /* ^E */,
+ cntrl /* ^F */,
+ cntrl /* ^G */,
+ cntrl /* ^H */,
+ ctype_base::mask(space | cntrl) /* tab */,
+ ctype_base::mask(space | cntrl) /* LF */,
+ ctype_base::mask(space | cntrl) /* ^K */,
+ ctype_base::mask(space | cntrl) /* FF */,
+ ctype_base::mask(space | cntrl) /* ^M */,
+ cntrl /* ^N */,
+ cntrl /* ^O */,
+ cntrl /* ^P */,
+ cntrl /* ^Q */,
+ cntrl /* ^R */,
+ cntrl /* ^S */,
+ cntrl /* ^T */,
+ cntrl /* ^U */,
+ cntrl /* ^V */,
+ cntrl /* ^W */,
+ cntrl /* ^X */,
+ cntrl /* ^Y */,
+ cntrl /* ^Z */,
+ cntrl /* esc */,
+ cntrl /* ^\ */,
+ cntrl /* ^] */,
+ cntrl /* ^^ */,
+ cntrl /* ^_ */,
+ ctype_base::mask(space | print) /* */,
+ ctype_base::mask(punct | print) /* ! */,
+ ctype_base::mask(punct | print) /* " */,
+ ctype_base::mask(punct | print) /* # */,
+ ctype_base::mask(punct | print) /* $ */,
+ ctype_base::mask(punct | print) /* % */,
+ ctype_base::mask(punct | print) /* & */,
+ ctype_base::mask(punct | print) /* ' */,
+ ctype_base::mask(punct | print) /* ( */,
+ ctype_base::mask(punct | print) /* ) */,
+ ctype_base::mask(punct | print) /* * */,
+ ctype_base::mask(punct | print) /* + */,
+ ctype_base::mask(punct | print) /* , */,
+ ctype_base::mask(punct | print) /* - */,
+ ctype_base::mask(punct | print) /* . */,
+ ctype_base::mask(punct | print) /* / */,
+ ctype_base::mask(digit | xdigit | print) /* 0 */,
+ ctype_base::mask(digit | xdigit | print) /* 1 */,
+ ctype_base::mask(digit | xdigit | print) /* 2 */,
+ ctype_base::mask(digit | xdigit | print) /* 3 */,
+ ctype_base::mask(digit | xdigit | print) /* 4 */,
+ ctype_base::mask(digit | xdigit | print) /* 5 */,
+ ctype_base::mask(digit | xdigit | print) /* 6 */,
+ ctype_base::mask(digit | xdigit | print) /* 7 */,
+ ctype_base::mask(digit | xdigit | print) /* 8 */,
+ ctype_base::mask(digit | xdigit | print) /* 9 */,
+ ctype_base::mask(punct | print) /* : */,
+ ctype_base::mask(punct | print) /* ; */,
+ ctype_base::mask(punct | print) /* < */,
+ ctype_base::mask(punct | print) /* = */,
+ ctype_base::mask(punct | print) /* > */,
+ ctype_base::mask(punct | print) /* ? */,
+ ctype_base::mask(punct | print) /* ! */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* A */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* B */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* C */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* D */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* E */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* F */,
+ ctype_base::mask(alpha | upper | print) /* G */,
+ ctype_base::mask(alpha | upper | print) /* H */,
+ ctype_base::mask(alpha | upper | print) /* I */,
+ ctype_base::mask(alpha | upper | print) /* J */,
+ ctype_base::mask(alpha | upper | print) /* K */,
+ ctype_base::mask(alpha | upper | print) /* L */,
+ ctype_base::mask(alpha | upper | print) /* M */,
+ ctype_base::mask(alpha | upper | print) /* N */,
+ ctype_base::mask(alpha | upper | print) /* O */,
+ ctype_base::mask(alpha | upper | print) /* P */,
+ ctype_base::mask(alpha | upper | print) /* Q */,
+ ctype_base::mask(alpha | upper | print) /* R */,
+ ctype_base::mask(alpha | upper | print) /* S */,
+ ctype_base::mask(alpha | upper | print) /* T */,
+ ctype_base::mask(alpha | upper | print) /* U */,
+ ctype_base::mask(alpha | upper | print) /* V */,
+ ctype_base::mask(alpha | upper | print) /* W */,
+ ctype_base::mask(alpha | upper | print) /* X */,
+ ctype_base::mask(alpha | upper | print) /* Y */,
+ ctype_base::mask(alpha | upper | print) /* Z */,
+ ctype_base::mask(punct | print) /* [ */,
+ ctype_base::mask(punct | print) /* \ */,
+ ctype_base::mask(punct | print) /* ] */,
+ ctype_base::mask(punct | print) /* ^ */,
+ ctype_base::mask(punct | print) /* _ */,
+ ctype_base::mask(punct | print) /* ` */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* a */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* b */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* c */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* d */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* e */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* f */,
+ ctype_base::mask(alpha | lower | print) /* g */,
+ ctype_base::mask(alpha | lower | print) /* h */,
+ ctype_base::mask(alpha | lower | print) /* i */,
+ ctype_base::mask(alpha | lower | print) /* j */,
+ ctype_base::mask(alpha | lower | print) /* k */,
+ ctype_base::mask(alpha | lower | print) /* l */,
+ ctype_base::mask(alpha | lower | print) /* m */,
+ ctype_base::mask(alpha | lower | print) /* n */,
+ ctype_base::mask(alpha | lower | print) /* o */,
+ ctype_base::mask(alpha | lower | print) /* p */,
+ ctype_base::mask(alpha | lower | print) /* q */,
+ ctype_base::mask(alpha | lower | print) /* r */,
+ ctype_base::mask(alpha | lower | print) /* s */,
+ ctype_base::mask(alpha | lower | print) /* t */,
+ ctype_base::mask(alpha | lower | print) /* u */,
+ ctype_base::mask(alpha | lower | print) /* v */,
+ ctype_base::mask(alpha | lower | print) /* w */,
+ ctype_base::mask(alpha | lower | print) /* x */,
+ ctype_base::mask(alpha | lower | print) /* y */,
+ ctype_base::mask(alpha | lower | print) /* x */,
+ ctype_base::mask(punct | print) /* { */,
+ ctype_base::mask(punct | print) /* | */,
+ ctype_base::mask(punct | print) /* } */,
+ ctype_base::mask(punct | print) /* ~ */,
+ cntrl /* del (0x7f)*/,
+ /* The next 128 entries are all 0. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ return _S_classic_table;
+ }
+
+ ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
+ size_t __refs)
+ : facet(__refs), _M_del(__table != 0 && __del),
+ _M_toupper(NULL), _M_tolower(NULL),
+ _M_table(__table ? __table : classic_table())
+ {
+ memset(_M_widen, 0, sizeof(_M_widen));
+ _M_widen_ok = 0;
+ memset(_M_narrow, 0, sizeof(_M_narrow));
+ _M_narrow_ok = 0;
+ }
+
+ ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
+ : facet(__refs), _M_del(__table != 0 && __del),
+ _M_toupper(NULL), _M_tolower(NULL),
+ _M_table(__table ? __table : classic_table())
+ {
+ memset(_M_widen, 0, sizeof(_M_widen));
+ _M_widen_ok = 0;
+ memset(_M_narrow, 0, sizeof(_M_narrow));
+ _M_narrow_ok = 0;
+ }
+
+ char
+ ctype<char>::do_toupper(char __c) const
+ { return (this->is(ctype_base::lower, __c) ? (__c - 'a' + 'A') : __c); }
+
+ const char*
+ ctype<char>::do_toupper(char* __low, const char* __high) const
+ {
+ while (__low < __high)
+ {
+ *__low = this->do_toupper(*__low);
+ ++__low;
+ }
+ return __high;
+ }
+
+ char
+ ctype<char>::do_tolower(char __c) const
+ { return (this->is(ctype_base::upper, __c) ? (__c - 'A' + 'a') : __c); }
+
+ const char*
+ ctype<char>::do_tolower(char* __low, const char* __high) const
+ {
+ while (__low < __high)
+ {
+ *__low = this->do_tolower(*__low);
+ ++__low;
+ }
+ return __high;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_inline.h b/libstdc++-v3/config/os/mingw32-w64/ctype_inline.h
new file mode 100644
index 00000000000..f1b9f6c6617
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_inline.h
@@ -0,0 +1,75 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2000, 2009, 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file bits/ctype_inline.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{locale}
+ */
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
+// functions go in ctype.cc
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ bool
+ ctype<char>::
+ is(mask __m, char __c) const
+ { return (_M_table[static_cast<unsigned char>(__c) ] & __m); }
+
+
+ const char*
+ ctype<char>::
+ is(const char* __low, const char* __high, mask* __vec) const
+ {
+ while (__low < __high)
+ *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
+ return __high;
+ }
+
+ const char*
+ ctype<char>::
+ scan_is(mask __m, const char* __low, const char* __high) const
+ {
+ while (__low < __high && !this->is(__m, *__low))
+ ++__low;
+ return __low;
+ }
+
+ const char*
+ ctype<char>::
+ scan_not(mask __m, const char* __low, const char* __high) const
+ {
+ while (__low < __high && this->is(__m, *__low) != 0)
+ ++__low;
+ return __low;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/mingw32-w64/error_constants.h b/libstdc++-v3/config/os/mingw32-w64/error_constants.h
new file mode 100644
index 00000000000..da2d311762c
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/error_constants.h
@@ -0,0 +1,142 @@
+// Specific definitions for mingw32 platform -*- C++ -*-
+
+// Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file bits/error_constants.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{system_error}
+ */
+
+#ifndef _GLIBCXX_ERROR_CONSTANTS
+# define _GLIBCXX_ERROR_CONSTANTS
+
+#include <bits/c++config.h>
+#include <cerrno>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+// Most of the commented-out error codes are socket-related and could be
+// replaced by Winsock WSA-prefixed equivalents.
+ enum class errc
+ {
+// address_family_not_supported = EAFNOSUPPORT,
+// address_in_use = EADDRINUSE,
+// address_not_available = EADDRNOTAVAIL,
+// already_connected = EISCONN,
+ argument_list_too_long = E2BIG,
+ argument_out_of_domain = EDOM,
+ bad_address = EFAULT,
+ bad_file_descriptor = EBADF,
+// bad_message = EBADMSG,
+ broken_pipe = EPIPE,
+// connection_aborted = ECONNABORTED,
+// connection_already_in_progress = EALREADY,
+// connection_refused = ECONNREFUSED,
+// connection_reset = ECONNRESET,
+// cross_device_link = EXDEV,
+// destination_address_required = EDESTADDRREQ,
+ device_or_resource_busy = EBUSY,
+ directory_not_empty = ENOTEMPTY,
+ executable_format_error = ENOEXEC,
+ file_exists = EEXIST,
+ file_too_large = EFBIG,
+ filename_too_long = ENAMETOOLONG,
+ function_not_supported = ENOSYS,
+// host_unreachable = EHOSTUNREACH,
+// identifier_removed = EIDRM,
+ illegal_byte_sequence = EILSEQ,
+ inappropriate_io_control_operation = ENOTTY,
+ interrupted = EINTR,
+ invalid_argument = EINVAL,
+ invalid_seek = ESPIPE,
+ io_error = EIO,
+ is_a_directory = EISDIR,
+// message_size = EMSGSIZE,
+// network_down = ENETDOWN,
+// network_reset = ENETRESET,
+// network_unreachable = ENETUNREACH,
+// no_buffer_space = ENOBUFS,
+#ifdef _GLIBCXX_HAVE_ECHILD
+ no_child_process = ECHILD,
+#endif
+// no_link = ENOLINK,
+ no_lock_available = ENOLCK,
+// no_message_available = ENODATA,
+// no_message = ENOMSG,
+// no_protocol_option = ENOPROTOOPT,
+#ifdef _GLIBCXX_HAVE_ENOSPC
+ no_space_on_device = ENOSPC,
+#endif
+// no_stream_resources = ENOSR,
+ no_such_device_or_address = ENXIO,
+ no_such_device = ENODEV,
+ no_such_file_or_directory = ENOENT,
+ no_such_process = ESRCH,
+ not_a_directory = ENOTDIR,
+// not_a_socket = ENOTSOCK,
+// not_a_stream = ENOSTR,
+// not_connected = ENOTCONN,
+ not_enough_memory = ENOMEM,
+#ifdef _GLIBCXX_HAVE_ENOTSUP
+ not_supported = ENOTSUP,
+#endif
+// operation_canceled = ECANCELED,
+// operation_in_progress = EINPROGRESS,
+#ifdef _GLIBCXX_HAVE_EPERM
+ operation_not_permitted = EPERM,
+#endif
+// operation_not_supported = EOPNOTSUPP,
+#ifdef _GLIBCXX_HAVE_EWOULDBLOCK
+ operation_would_block = EWOULDBLOCK,
+#endif
+// owner_dead = EOWNERDEAD,
+ permission_denied = EACCES,
+// protocol_error = EPROTO,
+// protocol_not_supported = EPROTONOSUPPORT,
+ read_only_file_system = EROFS,
+ resource_deadlock_would_occur = EDEADLK,
+ resource_unavailable_try_again = EAGAIN,
+ result_out_of_range = ERANGE,
+// state_not_recoverable = ENOTRECOVERABLE,
+// stream_timeout = ETIME,
+// text_file_busy = ETXTBSY,
+#ifdef _GLIBCXX_HAVE_ETIMEDOUT
+ timed_out = ETIMEDOUT,
+#endif
+ too_many_files_open_in_system = ENFILE,
+ too_many_files_open = EMFILE,
+ too_many_links = EMLINK
+// too_many_symbolic_link_levels = ELOOP,
+#ifdef _GLIBCXX_HAVE_EOVERFLOW
+ ,
+ value_too_large = EOVERFLOW
+#endif
+// wrong_protocol_type = EPROTOTYPE
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif
diff --git a/libstdc++-v3/config/os/mingw32-w64/os_defines.h b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
new file mode 100644
index 00000000000..c483a92e6da
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
@@ -0,0 +1,68 @@
+// Specific definitions for generic platforms -*- C++ -*-
+
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+// 2009, 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file bits/os_defines.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{iosfwd}
+ */
+
+#ifndef _GLIBCXX_OS_DEFINES
+# define _GLIBCXX_OS_DEFINES
+
+// System-specific #define, typedefs, corrections, etc, go here. This
+// file will come before all others.
+
+// Define as 0, if you want, to enable inlining of gthread functions.
+// By default, don't pollute libstdc++ with win32api names.
+#if !defined (__GTHREAD_HIDE_WIN32API)
+# define __GTHREAD_HIDE_WIN32API 1
+#endif
+
+// Don't let win32api windef.h define min and max as macros
+// if included after c++config.h.
+#undef NOMINMAX
+#define NOMINMAX 1
+
+#if defined (_GLIBCXX_DLL)
+#define _GLIBCXX_PSEUDO_VISIBILITY_default __attribute__ ((__dllimport__))
+#else
+#define _GLIBCXX_PSEUDO_VISIBILITY_default
+#endif
+#define _GLIBCXX_PSEUDO_VISIBILITY_hidden
+
+#define _GLIBCXX_PSEUDO_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY_ ## V
+
+// See libstdc++/20806.
+#define _GLIBCXX_HAVE_DOS_BASED_FILESYSTEM 1
+
+// See libstdc++/37522.
+#define _GLIBCXX_HAVE_BROKEN_VSWPRINTF 1
+
+// See libstdc++/43738
+// On native windows targets there is no ioctl function. And the existing
+// ioctlsocket function doesn't work for normal file-descriptors.
+#define _GLIBCXX_NO_IOCTL 1
+
+#endif
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 4fcf3d771c4..b91a18c47fe 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -17255,10 +17255,15 @@ fi
if test $enable_fully_dynamic_string = yes; then
+ enable_fully_dynamic_string_def=1
+ else
+ enable_fully_dynamic_string_def=0
+ fi
-$as_echo "#define _GLIBCXX_FULLY_DYNAMIC_STRING 1" >>confdefs.h
+cat >>confdefs.h <<_ACEOF
+#define _GLIBCXX_FULLY_DYNAMIC_STRING ${enable_fully_dynamic_string_def}
+_ACEOF
- fi
diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
index 799cec2f412..4da4508fa4f 100644
--- a/libstdc++-v3/configure.host
+++ b/libstdc++-v3/configure.host
@@ -260,8 +260,16 @@ case "${host_os}" in
atomic_word_dir=os/irix
;;
mingw32*)
- os_include_dir="os/mingw32"
- error_constants_dir="os/mingw32"
+ case "$host" in
+ *-w64-*)
+ os_include_dir="os/mingw32-w64"
+ error_constants_dir="os/mingw32-w64"
+ ;;
+ *)
+ os_include_dir="os/mingw32"
+ error_constants_dir="os/mingw32"
+ ;;
+ esac
OPT_LDFLAGS="${OPT_LDFLAGS} \$(lt_host_flags)"
;;
netbsd*)
diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index def04065751..0b01ceb61e6 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -746,6 +746,10 @@ INPUT = @srcdir@/doc/doxygen/doxygroups.cc \
include/tr1/ctime \
include/tr1/cwchar \
include/tr1/cwctype \
+ include/tr2/bool_set \
+ include/tr2/dynamic_bitset \
+ include/tr2/ratio \
+ include/tr2/type_traits \
include/decimal/decimal \
include/ext \
include/ext/pb_ds \
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index c3a7aeb005d..1c3db3b17db 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -79,7 +79,7 @@ std_headers = \
bits_srcdir = ${glibcxx_srcdir}/include/bits
bits_builddir = ./bits
bits_headers = \
- ${bits_srcdir}/algorithmfwd.h \
+ ${bits_srcdir}/algorithmfwd.h \
${bits_srcdir}/alloc_traits.h \
${bits_srcdir}/allocator.h \
${bits_srcdir}/atomic_base.h \
@@ -179,11 +179,11 @@ bits_headers = \
bits_sup_srcdir = ${glibcxx_srcdir}/libsupc++
bits_sup_headers = \
- ${bits_sup_srcdir}/cxxabi_forced.h \
- ${bits_sup_srcdir}/exception_defines.h \
- ${bits_sup_srcdir}/exception_ptr.h \
- ${bits_sup_srcdir}/hash_bytes.h \
- ${bits_sup_srcdir}/nested_exception.h
+ ${bits_sup_srcdir}/cxxabi_forced.h \
+ ${bits_sup_srcdir}/exception_defines.h \
+ ${bits_sup_srcdir}/exception_ptr.h \
+ ${bits_sup_srcdir}/hash_bytes.h \
+ ${bits_sup_srcdir}/nested_exception.h
backward_srcdir = ${glibcxx_srcdir}/include/backward
backward_builddir = ./backward
@@ -269,7 +269,7 @@ pb_headers1 = \
${pb_srcdir}/detail/binomial_heap_/binomial_heap_.hpp \
${pb_srcdir}/detail/binomial_heap_/constructors_destructor_fn_imps.hpp \
${pb_srcdir}/detail/binomial_heap_/debug_fn_imps.hpp \
- ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
+ ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
pb_headers2 = \
${pb_srcdir}/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp \
@@ -604,6 +604,15 @@ tr1_headers = \
${tr1_srcdir}/wchar.h \
${tr1_srcdir}/wctype.h
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+ ${tr2_srcdir}/bool_set \
+ ${tr2_srcdir}/bool_set.tcc \
+ ${tr2_srcdir}/dynamic_bitset \
+ ${tr2_srcdir}/ratio \
+ ${tr2_srcdir}/type_traits
+
decimal_srcdir = ${glibcxx_srcdir}/include/decimal
decimal_builddir = ./decimal
decimal_headers = \
@@ -720,49 +729,49 @@ parallel_srcdir = ${glibcxx_srcdir}/include/parallel
parallel_builddir = ./parallel
if ENABLE_PARALLEL
parallel_headers = \
- ${parallel_srcdir}/algo.h \
- ${parallel_srcdir}/algobase.h \
- ${parallel_srcdir}/algorithm \
- ${parallel_srcdir}/algorithmfwd.h \
- ${parallel_srcdir}/balanced_quicksort.h \
- ${parallel_srcdir}/base.h \
- ${parallel_srcdir}/basic_iterator.h \
- ${parallel_srcdir}/checkers.h \
- ${parallel_srcdir}/compatibility.h \
- ${parallel_srcdir}/compiletime_settings.h \
- ${parallel_srcdir}/equally_split.h \
- ${parallel_srcdir}/features.h \
- ${parallel_srcdir}/find.h \
- ${parallel_srcdir}/find_selectors.h \
- ${parallel_srcdir}/for_each.h \
- ${parallel_srcdir}/for_each_selectors.h \
- ${parallel_srcdir}/iterator.h \
- ${parallel_srcdir}/list_partition.h \
- ${parallel_srcdir}/losertree.h \
- ${parallel_srcdir}/merge.h \
- ${parallel_srcdir}/multiseq_selection.h \
- ${parallel_srcdir}/multiway_merge.h \
- ${parallel_srcdir}/multiway_mergesort.h \
- ${parallel_srcdir}/numeric \
- ${parallel_srcdir}/numericfwd.h \
- ${parallel_srcdir}/omp_loop.h \
- ${parallel_srcdir}/omp_loop_static.h \
- ${parallel_srcdir}/par_loop.h \
- ${parallel_srcdir}/parallel.h \
- ${parallel_srcdir}/partial_sum.h \
- ${parallel_srcdir}/partition.h \
- ${parallel_srcdir}/queue.h \
- ${parallel_srcdir}/quicksort.h \
- ${parallel_srcdir}/random_number.h \
- ${parallel_srcdir}/random_shuffle.h \
- ${parallel_srcdir}/search.h \
- ${parallel_srcdir}/set_operations.h \
- ${parallel_srcdir}/settings.h \
- ${parallel_srcdir}/sort.h \
- ${parallel_srcdir}/tags.h \
- ${parallel_srcdir}/types.h \
- ${parallel_srcdir}/unique_copy.h \
- ${parallel_srcdir}/workstealing.h
+ ${parallel_srcdir}/algo.h \
+ ${parallel_srcdir}/algobase.h \
+ ${parallel_srcdir}/algorithm \
+ ${parallel_srcdir}/algorithmfwd.h \
+ ${parallel_srcdir}/balanced_quicksort.h \
+ ${parallel_srcdir}/base.h \
+ ${parallel_srcdir}/basic_iterator.h \
+ ${parallel_srcdir}/checkers.h \
+ ${parallel_srcdir}/compatibility.h \
+ ${parallel_srcdir}/compiletime_settings.h \
+ ${parallel_srcdir}/equally_split.h \
+ ${parallel_srcdir}/features.h \
+ ${parallel_srcdir}/find.h \
+ ${parallel_srcdir}/find_selectors.h \
+ ${parallel_srcdir}/for_each.h \
+ ${parallel_srcdir}/for_each_selectors.h \
+ ${parallel_srcdir}/iterator.h \
+ ${parallel_srcdir}/list_partition.h \
+ ${parallel_srcdir}/losertree.h \
+ ${parallel_srcdir}/merge.h \
+ ${parallel_srcdir}/multiseq_selection.h \
+ ${parallel_srcdir}/multiway_merge.h \
+ ${parallel_srcdir}/multiway_mergesort.h \
+ ${parallel_srcdir}/numeric \
+ ${parallel_srcdir}/numericfwd.h \
+ ${parallel_srcdir}/omp_loop.h \
+ ${parallel_srcdir}/omp_loop_static.h \
+ ${parallel_srcdir}/par_loop.h \
+ ${parallel_srcdir}/parallel.h \
+ ${parallel_srcdir}/partial_sum.h \
+ ${parallel_srcdir}/partition.h \
+ ${parallel_srcdir}/queue.h \
+ ${parallel_srcdir}/quicksort.h \
+ ${parallel_srcdir}/random_number.h \
+ ${parallel_srcdir}/random_shuffle.h \
+ ${parallel_srcdir}/search.h \
+ ${parallel_srcdir}/set_operations.h \
+ ${parallel_srcdir}/settings.h \
+ ${parallel_srcdir}/sort.h \
+ ${parallel_srcdir}/tags.h \
+ ${parallel_srcdir}/types.h \
+ ${parallel_srcdir}/unique_copy.h \
+ ${parallel_srcdir}/workstealing.h
else
parallel_headers =
endif
@@ -887,9 +896,9 @@ endif
# CLEANFILES and all-local are kept up-to-date.
allstamped = \
stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
- stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+ stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
- stamp-host
+ stamp-host
# List of all files that are created by explicit building, editing, or
# catenation.
@@ -1003,6 +1012,11 @@ stamp-tr1: ${tr1_headers}
@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
@$(STAMP) stamp-tr1
+stamp-tr2: ${tr2_headers}
+ @-mkdir -p ${tr2_builddir}
+ @-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+ @$(STAMP) stamp-tr2
+
stamp-decimal: ${decimal_headers}
@-mkdir -p ${decimal_builddir}
@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1095,7 +1109,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "s,define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY, define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY $$visibility," \
-e "s,define _GLIBCXX_EXTERN_TEMPLATE, define _GLIBCXX_EXTERN_TEMPLATE $$externtemplate," \
-e "$$ldbl_compat" \
- < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
+ < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
-e 's/VERSION/_GLIBCXX_VERSION/g' \
@@ -1246,6 +1260,9 @@ install-headers:
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
for file in ${tr1_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+ for file in ${tr2_headers}; do \
+ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
for file in ${decimal_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1292,7 +1309,7 @@ clean-local:
# developer tries to create them via make in the include build
# directory. (This is more of an example of how this kind of rule can
# be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
$(decimal_headers) $(ext_headers)
$(std_headers): ; @:
$(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 66d3187b455..d392a9f818e 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -331,7 +331,7 @@ std_headers = \
bits_srcdir = ${glibcxx_srcdir}/include/bits
bits_builddir = ./bits
bits_headers = \
- ${bits_srcdir}/algorithmfwd.h \
+ ${bits_srcdir}/algorithmfwd.h \
${bits_srcdir}/alloc_traits.h \
${bits_srcdir}/allocator.h \
${bits_srcdir}/atomic_base.h \
@@ -431,11 +431,11 @@ bits_headers = \
bits_sup_srcdir = ${glibcxx_srcdir}/libsupc++
bits_sup_headers = \
- ${bits_sup_srcdir}/cxxabi_forced.h \
- ${bits_sup_srcdir}/exception_defines.h \
- ${bits_sup_srcdir}/exception_ptr.h \
- ${bits_sup_srcdir}/hash_bytes.h \
- ${bits_sup_srcdir}/nested_exception.h
+ ${bits_sup_srcdir}/cxxabi_forced.h \
+ ${bits_sup_srcdir}/exception_defines.h \
+ ${bits_sup_srcdir}/exception_ptr.h \
+ ${bits_sup_srcdir}/hash_bytes.h \
+ ${bits_sup_srcdir}/nested_exception.h
backward_srcdir = ${glibcxx_srcdir}/include/backward
backward_builddir = ./backward
@@ -520,7 +520,7 @@ pb_headers1 = \
${pb_srcdir}/detail/binomial_heap_/binomial_heap_.hpp \
${pb_srcdir}/detail/binomial_heap_/constructors_destructor_fn_imps.hpp \
${pb_srcdir}/detail/binomial_heap_/debug_fn_imps.hpp \
- ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
+ ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
pb_headers2 = \
${pb_srcdir}/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp \
@@ -854,6 +854,15 @@ tr1_headers = \
${tr1_srcdir}/wchar.h \
${tr1_srcdir}/wctype.h
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+ ${tr2_srcdir}/bool_set \
+ ${tr2_srcdir}/bool_set.tcc \
+ ${tr2_srcdir}/dynamic_bitset \
+ ${tr2_srcdir}/ratio \
+ ${tr2_srcdir}/type_traits
+
decimal_srcdir = ${glibcxx_srcdir}/include/decimal
decimal_builddir = ./decimal
decimal_headers = \
@@ -966,49 +975,49 @@ parallel_srcdir = ${glibcxx_srcdir}/include/parallel
parallel_builddir = ./parallel
@ENABLE_PARALLEL_FALSE@parallel_headers =
@ENABLE_PARALLEL_TRUE@parallel_headers = \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algo.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algobase.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithm \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithmfwd.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/balanced_quicksort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/base.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/basic_iterator.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/checkers.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compatibility.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compiletime_settings.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/equally_split.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/features.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find_selectors.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each_selectors.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/iterator.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/list_partition.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/losertree.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/merge.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiseq_selection.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_merge.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_mergesort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numeric \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numericfwd.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop_static.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/par_loop.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/parallel.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partial_sum.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partition.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/queue.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/quicksort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_number.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_shuffle.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/search.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/set_operations.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/settings.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/sort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/tags.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/types.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/unique_copy.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/workstealing.h
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algo.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algobase.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithm \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithmfwd.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/balanced_quicksort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/base.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/basic_iterator.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/checkers.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compatibility.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compiletime_settings.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/equally_split.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/features.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find_selectors.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each_selectors.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/iterator.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/list_partition.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/losertree.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/merge.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiseq_selection.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_merge.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_mergesort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numeric \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numericfwd.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop_static.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/par_loop.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/parallel.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partial_sum.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partition.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/queue.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/quicksort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_number.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_shuffle.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/search.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/set_operations.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/settings.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/sort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/tags.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/types.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/unique_copy.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/workstealing.h
# Profile mode headers
@@ -1125,9 +1134,9 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS)
# CLEANFILES and all-local are kept up-to-date.
allstamped = \
stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
- stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+ stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
- stamp-host
+ stamp-host
# List of all files that are created by explicit building, editing, or
@@ -1403,6 +1412,11 @@ stamp-tr1: ${tr1_headers}
@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
@$(STAMP) stamp-tr1
+stamp-tr2: ${tr2_headers}
+ @-mkdir -p ${tr2_builddir}
+ @-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+ @$(STAMP) stamp-tr2
+
stamp-decimal: ${decimal_headers}
@-mkdir -p ${decimal_builddir}
@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1486,7 +1500,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "s,define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY, define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY $$visibility," \
-e "s,define _GLIBCXX_EXTERN_TEMPLATE, define _GLIBCXX_EXTERN_TEMPLATE $$externtemplate," \
-e "$$ldbl_compat" \
- < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
+ < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
-e 's/VERSION/_GLIBCXX_VERSION/g' \
@@ -1631,6 +1645,9 @@ install-headers:
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
for file in ${tr1_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+ for file in ${tr2_headers}; do \
+ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
for file in ${decimal_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1674,7 +1691,7 @@ clean-local:
# developer tries to create them via make in the include build
# directory. (This is more of an example of how this kind of rule can
# be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
$(decimal_headers) $(ext_headers)
$(std_headers): ; @:
$(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 55513ea910f..5708194bd01 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -201,7 +201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_set_length_and_sharable(size_type __n)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
{
@@ -231,7 +231,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_dispose(const _Alloc& __a)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
{
@@ -252,7 +252,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_CharT*
_M_refcopy() throw()
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
__gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);
@@ -430,7 +430,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @brief Default constructor creates an empty string.
*/
basic_string()
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
: _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { }
#else
: _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc()){ }
@@ -502,7 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string(basic_string&& __str) noexcept
: _M_dataplus(__str._M_dataplus)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
__str._M_data(_S_empty_rep()._M_refdata());
#else
__str._M_data(_S_construct(size_type(), _CharT(), get_allocator()));
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 056e2657390..7eff81819f6 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -80,7 +80,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
input_iterator_tag)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
@@ -126,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
forward_iterator_tag)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
@@ -154,7 +154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string<_CharT, _Traits, _Alloc>::
_S_construct(size_type __n, _CharT __c, const _Alloc& __a)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__n == 0 && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
@@ -456,7 +456,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string<_CharT, _Traits, _Alloc>::
_M_leak_hard()
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (_M_rep() == &_S_empty_rep())
return;
#endif
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 8c61de311d4..f77da5ee1a7 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -103,9 +103,11 @@
# ifdef __GXX_EXPERIMENTAL_CXX0X__
# define _GLIBCXX_NOEXCEPT noexcept
# define _GLIBCXX_USE_NOEXCEPT noexcept
+# define _GLIBCXX_THROW(_EXC)
# else
# define _GLIBCXX_NOEXCEPT
# define _GLIBCXX_USE_NOEXCEPT throw()
+# define _GLIBCXX_THROW(_EXC) throw(_EXC)
# endif
#endif
diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h
index 2570f4c6104..f485c170dea 100644
--- a/libstdc++-v3/include/bits/codecvt.h
+++ b/libstdc++-v3/include/bits/codecvt.h
@@ -292,7 +292,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit
codecvt(size_t __refs = 0)
- : __codecvt_abstract_base<_InternT, _ExternT, _StateT> (__refs) { }
+ : __codecvt_abstract_base<_InternT, _ExternT, _StateT> (__refs),
+ _M_c_locale_codecvt(0)
+ { }
explicit
codecvt(__c_locale __cloc, size_t __refs = 0);
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index a125f3eb80a..95d06b21262 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -374,14 +374,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert_bucket(_Arg&&, size_type,
typename _Hashtable::_Hash_code_type);
- template<typename _Arg>
- std::pair<iterator, bool>
- _M_insert(_Arg&&, std::true_type);
-
- template<typename _Arg>
- iterator
- _M_insert(_Arg&&, std::false_type);
-
typedef typename std::conditional<__unique_keys,
std::pair<iterator, bool>,
iterator>::type
@@ -393,38 +385,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>::type
_Insert_Conv_Type;
+ protected:
+ template<typename _Arg>
+ std::pair<iterator, bool>
+ _M_insert(_Arg&&, std::true_type);
+
+ template<typename _Arg>
+ iterator
+ _M_insert(_Arg&&, std::false_type);
+
public:
// Insert and erase
_Insert_Return_Type
insert(const value_type& __v)
- { return _M_insert(__v, std::integral_constant<bool, __unique_keys>()); }
+ { return _M_insert(__v, integral_constant<bool, __unique_keys>()); }
iterator
insert(const_iterator, const value_type& __v)
{ return _Insert_Conv_Type()(insert(__v)); }
- _Insert_Return_Type
- insert(value_type&& __v)
- { return _M_insert(std::move(__v),
- std::integral_constant<bool, __unique_keys>()); }
-
- iterator
- insert(const_iterator, value_type&& __v)
- { return _Insert_Conv_Type()(insert(std::move(__v))); }
-
template<typename _Pair, typename = typename
- std::enable_if<!__constant_iterators
- && std::is_convertible<_Pair,
- value_type>::value>::type>
+ std::enable_if<__and_<integral_constant<bool, !__constant_iterators>,
+ std::is_convertible<_Pair,
+ value_type>>::value>::type>
_Insert_Return_Type
insert(_Pair&& __v)
{ return _M_insert(std::forward<_Pair>(__v),
- std::integral_constant<bool, __unique_keys>()); }
+ integral_constant<bool, __unique_keys>()); }
template<typename _Pair, typename = typename
- std::enable_if<!__constant_iterators
- && std::is_convertible<_Pair,
- value_type>::value>::type>
+ std::enable_if<__and_<integral_constant<bool, !__constant_iterators>,
+ std::is_convertible<_Pair,
+ value_type>>::value>::type>
iterator
insert(const_iterator, _Pair&& __v)
{ return _Insert_Conv_Type()(insert(std::forward<_Pair>(__v))); }
diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc
index 01c1bc64495..55156bbf062 100644
--- a/libstdc++-v3/include/bits/list.tcc
+++ b/libstdc++-v3/include/bits/list.tcc
@@ -67,8 +67,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_clear()
{
typedef _List_node<_Tp> _Node;
- _Node* __cur = static_cast<_Node*>(this->_M_impl._M_node._M_next);
- while (__cur != &this->_M_impl._M_node)
+ _Node* __cur = static_cast<_Node*>(_M_impl._M_node._M_next);
+ while (__cur != &_M_impl._M_node)
{
_Node* __tmp = __cur;
__cur = static_cast<_Node*>(__cur->_M_next);
@@ -139,14 +139,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
list<_Tp, _Alloc>::
resize(size_type __new_size)
{
- iterator __i = begin();
- size_type __len = 0;
- for (; __i != end() && __len < __new_size; ++__i, ++__len)
- ;
- if (__len == __new_size)
- erase(__i, end());
- else // __i == end()
- _M_default_append(__new_size - __len);
+ if (__new_size > size())
+ _M_default_append(__new_size - size());
+ else if (__new_size < size())
+ {
+ iterator __i = begin();
+ std::advance(__i, __new_size);
+ erase(__i, end());
+ }
}
template<typename _Tp, typename _Alloc>
@@ -154,14 +154,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
list<_Tp, _Alloc>::
resize(size_type __new_size, const value_type& __x)
{
- iterator __i = begin();
- size_type __len = 0;
- for (; __i != end() && __len < __new_size; ++__i, ++__len)
- ;
- if (__len == __new_size)
- erase(__i, end());
- else // __i == end()
- insert(end(), __new_size - __len, __x);
+ if (__new_size > size())
+ insert(end(), __new_size - size(), __x);
+ else if (__new_size < size())
+ {
+ iterator __i = begin();
+ std::advance(__i, __new_size);
+ erase(__i, end());
+ }
}
#else
template<typename _Tp, typename _Alloc>
@@ -312,6 +312,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
++__first1;
if (__first2 != __last2)
_M_transfer(__last1, __first2, __last2);
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ this->_M_impl._M_size += __x.size();
+ __x._M_impl._M_size = 0;
+#endif
}
}
@@ -346,6 +351,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
++__first1;
if (__first2 != __last2)
_M_transfer(__last1, __first2, __last2);
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ this->_M_impl._M_size += __x.size();
+ __x._M_impl._M_size = 0;
+#endif
}
}
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index 42acace5b66..32addf95105 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -211,6 +211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __r A %shared_ptr.
* @post get() == __r.get() && use_count() == __r.use_count()
*/
+ shared_ptr(const shared_ptr&) noexcept = default;
template<typename _Tp1, typename = typename
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
@@ -264,6 +265,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr shared_ptr(nullptr_t __p) noexcept
: __shared_ptr<_Tp>(__p) { }
+ shared_ptr& operator=(const shared_ptr&) noexcept = default;
template<typename _Tp1>
shared_ptr&
operator=(const shared_ptr<_Tp1>& __r) noexcept
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index 9d3a970d2ca..a002461ae98 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -812,7 +812,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef typename iterator_traits<_II1>::value_type _ValueType1;
typedef typename iterator_traits<_II2>::value_type _ValueType2;
- const bool __simple = (__is_integer<_ValueType1>::__value
+ const bool __simple = ((__is_integer<_ValueType1>::__value
+ || __is_pointer<_ValueType1>::__value)
&& __is_pointer<_II1>::__value
&& __is_pointer<_II2>::__value
&& __are_same<_ValueType1, _ValueType2>::__value);
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 91e39f3256c..56ee2fbfd2e 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -306,22 +306,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
- struct _List_impl
+ struct _List_impl
: public _Node_alloc_type
{
__detail::_List_node_base _M_node;
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ size_t _M_size;
+#endif
+
_List_impl()
: _Node_alloc_type(), _M_node()
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ , _M_size(0)
+#endif
{ }
_List_impl(const _Node_alloc_type& __a)
: _Node_alloc_type(__a), _M_node()
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ , _M_size(0)
+#endif
{ }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
_List_impl(_Node_alloc_type&& __a)
- : _Node_alloc_type(std::move(__a)), _M_node()
+ : _Node_alloc_type(std::move(__a)), _M_node(), _M_size(0)
{ }
#endif
};
@@ -330,22 +340,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_List_node<_Tp>*
_M_get_node()
- { return _M_impl._Node_alloc_type::allocate(1); }
-
+ {
+ _List_node<_Tp>* __tmp = _M_impl._Node_alloc_type::allocate(1);
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ ++_M_impl._M_size;
+#endif
+ return __tmp;
+ }
+
void
_M_put_node(_List_node<_Tp>* __p)
- { _M_impl._Node_alloc_type::deallocate(__p, 1); }
+ {
+ _M_impl._Node_alloc_type::deallocate(__p, 1);
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ --_M_impl._M_size;
+#endif
+ }
public:
typedef _Alloc allocator_type;
_Node_alloc_type&
_M_get_Node_allocator() _GLIBCXX_NOEXCEPT
- { return *static_cast<_Node_alloc_type*>(&this->_M_impl); }
+ { return *static_cast<_Node_alloc_type*>(&_M_impl); }
const _Node_alloc_type&
_M_get_Node_allocator() const _GLIBCXX_NOEXCEPT
- { return *static_cast<const _Node_alloc_type*>(&this->_M_impl); }
+ { return *static_cast<const _Node_alloc_type*>(&_M_impl); }
_Tp_alloc_type
_M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
@@ -368,8 +389,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_impl(std::move(__x._M_get_Node_allocator()))
{
_M_init();
- __detail::_List_node_base::swap(this->_M_impl._M_node,
- __x._M_impl._M_node);
+ __detail::_List_node_base::swap(_M_impl._M_node, __x._M_impl._M_node);
+ std::swap(_M_impl._M_size, __x._M_impl._M_size);
}
#endif
@@ -851,7 +872,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/** Returns the number of elements in the %list. */
size_type
size() const _GLIBCXX_NOEXCEPT
- { return std::distance(begin(), end()); }
+ {
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ return this->_M_impl._M_size;
+#else
+ return std::distance(begin(), end());
+#endif
+ }
/** Returns the size() of the largest possible %list. */
size_type
@@ -1186,6 +1213,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
__detail::_List_node_base::swap(this->_M_impl._M_node,
__x._M_impl._M_node);
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ std::swap(this->_M_impl._M_size, __x._M_impl._M_size);
+#endif
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 431. Swapping containers with unequal allocators.
@@ -1230,6 +1260,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_check_equal_allocators(__x);
this->_M_transfer(__position, __x.begin(), __x.end());
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ this->_M_impl._M_size += __x.size();
+ __x._M_impl._M_size = 0;
+#endif
}
}
@@ -1261,7 +1296,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return;
if (this != &__x)
- _M_check_equal_allocators(__x);
+ {
+ _M_check_equal_allocators(__x);
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ ++this->_M_impl._M_size;
+ --__x._M_impl._M_size;
+#endif
+ }
this->_M_transfer(__position, __i, __j);
}
@@ -1296,7 +1338,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (__first != __last)
{
if (this != &__x)
- _M_check_equal_allocators(__x);
+ {
+ _M_check_equal_allocators(__x);
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ const size_type __size = std::distance(__first, __last);
+ this->_M_impl._M_size += __size;
+ __x._M_impl._M_size -= __size;
+#endif
+ }
this->_M_transfer(__position, __first, __last);
}
@@ -1571,6 +1621,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline bool
operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ return (__x.size() == __y.size()
+ && std::equal(__x.begin(), __x.end(), __y.begin()));
+#else
typedef typename list<_Tp, _Alloc>::const_iterator const_iterator;
const_iterator __end1 = __x.end();
const_iterator __end2 = __y.end();
@@ -1583,6 +1637,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
++__i2;
}
return __i1 == __end1 && __i2 == __end2;
+#endif
}
/**
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index f95f2463e49..8985c430f64 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -70,7 +70,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
struct _Vector_base
{
- typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
+ typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
+ rebind<_Tp>::other _Tp_alloc_type;
typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
pointer;
@@ -683,7 +684,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/** Returns the size() of the largest possible %vector. */
size_type
max_size() const _GLIBCXX_NOEXCEPT
- { return _M_get_Tp_allocator().max_size(); }
+ { return _Alloc_traits::max_size(_M_get_Tp_allocator()); }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
/**
diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h
index 38350bc390d..12b7bda138f 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -63,7 +63,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Base::hasher hasher;
typedef typename _Base::key_equal key_equal;
typedef typename _Base::allocator_type allocator_type;
-
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
+
explicit
__unordered_set(size_type __n = 10,
const hasher& __hf = hasher(),
@@ -103,6 +105,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
this->insert(__l.begin(), __l.end());
return *this;
}
+
+ using _Base::insert;
+
+ std::pair<iterator, bool>
+ insert(value_type&& __v)
+ { return this->_M_insert(std::move(__v), std::true_type()); }
+
+ iterator
+ insert(const_iterator, value_type&& __v)
+ { return insert(std::move(__v)).first; }
};
template<class _Value,
@@ -132,7 +144,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Base::hasher hasher;
typedef typename _Base::key_equal key_equal;
typedef typename _Base::allocator_type allocator_type;
-
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
+
explicit
__unordered_multiset(size_type __n = 10,
const hasher& __hf = hasher(),
@@ -173,6 +187,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
this->insert(__l.begin(), __l.end());
return *this;
}
+
+ using _Base::insert;
+
+ iterator
+ insert(value_type&& __v)
+ { return this->_M_insert(std::move(__v), std::false_type()); }
+
+ iterator
+ insert(const_iterator, value_type&& __v)
+ { return insert(std::move(__v)); }
};
template<class _Value, class _Hash, class _Pred, class _Alloc,
diff --git a/libstdc++-v3/include/ext/alloc_traits.h b/libstdc++-v3/include/ext/alloc_traits.h
index dbeb95f313c..de13b652521 100644
--- a/libstdc++-v3/include/ext/alloc_traits.h
+++ b/libstdc++-v3/include/ext/alloc_traits.h
@@ -106,6 +106,7 @@ template<typename _Alloc>
using _Base_type::deallocate;
using _Base_type::construct;
using _Base_type::destroy;
+ using _Base_type::max_size;
private:
template<typename _Ptr>
@@ -115,6 +116,7 @@ template<typename _Alloc>
{ };
public:
+ // overload construct for non-standard pointer types
template<typename _Ptr, typename... _Args>
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
construct(_Alloc& __a, _Ptr __p, _Args&&... __args)
@@ -123,6 +125,7 @@ template<typename _Alloc>
std::forward<_Args>(__args)...);
}
+ // overload destroy for non-standard pointer types
template<typename _Ptr>
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
destroy(_Alloc& __a, _Ptr __p)
@@ -156,6 +159,9 @@ template<typename _Alloc>
|| noexcept(swap(std::declval<_Alloc&>(), std::declval<_Alloc&>()));
}
+ template<typename _Tp>
+ struct rebind
+ { typedef typename _Base_type::template __rebind_alloc<_Tp>::__type other; };
#else
typedef typename _Alloc::pointer pointer;
@@ -179,6 +185,9 @@ template<typename _Alloc>
static void destroy(_Alloc& __a, pointer __p)
{ __a.destroy(__p); }
+ static size_type max_size(const _Alloc& __a)
+ { return __a.max_size(); }
+
static const _Alloc& _S_select_on_copy(const _Alloc& __a) { return __a; }
static void _S_on_swap(_Alloc& __a, _Alloc& __b)
@@ -187,6 +196,10 @@ template<typename _Alloc>
// 431. Swapping containers with unequal allocators.
std::__alloc_swap<_Alloc>::_S_do_it(__a, __b);
}
+
+ template<typename _Tp>
+ struct rebind
+ { typedef typename _Alloc::template rebind<_Tp>::other other; };
#endif
};
diff --git a/libstdc++-v3/include/ext/pod_char_traits.h b/libstdc++-v3/include/ext/pod_char_traits.h
index 3c9f0988a68..568af4b05b4 100644
--- a/libstdc++-v3/include/ext/pod_char_traits.h
+++ b/libstdc++-v3/include/ext/pod_char_traits.h
@@ -1,6 +1,7 @@
// POD character, std::char_traits specialization -*- C++ -*-
-// Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009, 2010, 2011
+// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -32,6 +33,8 @@
#ifndef _POD_CHAR_TRAITS_H
#define _POD_CHAR_TRAITS_H 1
+#pragma GCC system_header
+
#include <string>
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
diff --git a/libstdc++-v3/include/tr2/bool_set b/libstdc++-v3/include/tr2/bool_set
new file mode 100644
index 00000000000..fe322675991
--- /dev/null
+++ b/libstdc++-v3/include/tr2/bool_set
@@ -0,0 +1,320 @@
+// TR2 <bool_set> -*- C++ -*-
+
+// Copyright (C) 2009, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file tr2/bool_set
+ * This is a TR2 C++ Library header.
+ */
+
+//
+// Sort of an implementation of bool_set in n2136 Hervé Brönnimann,
+// Guillaume Melquiond, Sylvain Pion.
+//
+// The implicit conversion to bool is slippery! I may use the new
+// explicit conversion. This has been specialized in the language so
+// that in contexts requiring a bool the conversion happens
+// implicitly. Thus most objections should be eliminated.
+//
+
+#ifndef _GLIBCXX_TR2_BOOL_SET
+#define _GLIBCXX_TR2_BOOL_SET 1
+
+#pragma GCC system_header
+
+#include <typeinfo>
+#include <iostream>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ class bool_set
+ {
+ public:
+
+ /// Default constructor.
+ bool_set() : _M_b(_S_false) { }
+
+ /// Constructor from bool.
+ bool_set(bool __t) : _M_b(_Bool_set_val(__t)) { }
+
+ ///
+ // I'm not sure about this.
+ bool contains(bool_set __b) const
+ { return this->is_singleton() && this->equals(__b); }
+
+ /// Return true if states are equal.
+ bool equals(bool_set __b) const
+ { return __b._M_b == _M_b; }
+
+ /// Return true if this is empty.
+ bool is_emptyset() const
+ { return _M_b == _S_empty; }
+
+ /// Return true if this is indeterminate.
+ bool is_indeterminate() const
+ { return _M_b == _S_indet; }
+
+ /// Return true if this is false or true (normal boolean).
+ bool is_singleton() const
+ { return _M_b == _S_false || _M_b == _S_true_; }
+
+ /// Conversion to bool.
+ //explicit
+ operator bool() const
+ {
+ if (! is_singleton())
+ throw std::bad_cast();
+ return _M_b;
+ }
+
+ ///
+ static bool_set indeterminate()
+ {
+ bool_set __b;
+ __b._M_b = _S_indet;
+ return __b;
+ }
+
+ ///
+ static bool_set emptyset()
+ {
+ bool_set __b;
+ __b._M_b = _S_empty;
+ return __b;
+ }
+
+ friend bool_set
+ operator!(bool_set __b)
+ { return __b._M_not(); }
+
+ friend bool_set
+ operator^(bool_set __s, bool_set __t)
+ { return __s._M_xor(__t); }
+
+ friend bool_set
+ operator|(bool_set __s, bool_set __t)
+ { return __s._M_or(__t); }
+
+ friend bool_set
+ operator&(bool_set __s, bool_set __t)
+ { return __s._M_and(__t); }
+
+ friend bool_set
+ operator==(bool_set __s, bool_set __t)
+ { return __s._M_eq(__t); }
+
+
+ // These overloads replace the facet additions in the paper!
+
+ template<typename CharT, typename Traits>
+ friend std::basic_ostream<CharT, Traits>&
+ operator<<(std::basic_ostream<CharT, Traits>& __out, bool_set __b)
+ {
+ int __a = __b._M_b;
+ __out << __a;
+ }
+
+ template<typename CharT, typename Traits>
+ friend std::basic_istream<CharT, Traits>&
+ operator>>(std::basic_istream<CharT, Traits>& __in, bool_set& __b)
+ {
+ long __c;
+ __in >> __c;
+ if (__c >= _S_false && __c < _S_empty)
+ __b._M_b = static_cast<_Bool_set_val>(__c);
+ }
+
+ private:
+
+ ///
+ enum _Bool_set_val: unsigned char
+ {
+ _S_false = 0,
+ _S_true_ = 1,
+ _S_indet = 2,
+ _S_empty = 3
+ };
+
+ /// Bool set state.
+ _Bool_set_val _M_b;
+
+ ///
+ bool_set(_Bool_set_val __c) : _M_b(__c) { }
+
+ ///
+ bool_set _M_not() const
+ { return _S_not[this->_M_b]; }
+
+ ///
+ bool_set _M_xor(bool_set __b) const
+ { return _S_xor[this->_M_b][__b._M_b]; }
+
+ ///
+ bool_set _M_or(bool_set __b) const
+ { return _S_or[this->_M_b][__b._M_b]; }
+
+ ///
+ bool_set _M_and(bool_set __b) const
+ { return _S_and[this->_M_b][__b._M_b]; }
+
+ ///
+ bool_set _M_eq(bool_set __b) const
+ { return _S_eq[this->_M_b][__b._M_b]; }
+
+ ///
+ static _Bool_set_val _S_not[4];
+
+ ///
+ static _Bool_set_val _S_xor[4][4];
+
+ ///
+ static _Bool_set_val _S_or[4][4];
+
+ ///
+ static _Bool_set_val _S_and[4][4];
+
+ ///
+ static _Bool_set_val _S_eq[4][4];
+ };
+
+ // 20.2.3.2 bool_set values
+
+ inline bool
+ contains(bool_set __s, bool_set __t)
+ { return __s.contains(__t); }
+
+ inline bool
+ equals(bool_set __s, bool_set __t)
+ { return __s.equals(__t); }
+
+ inline bool
+ is_emptyset(bool_set __b)
+ { return __b.is_emptyset(); }
+
+ inline bool
+ is_indeterminate(bool_set __b)
+ { return __b.is_indeterminate(); }
+
+ inline bool
+ is_singleton(bool_set __b)
+ { return __b.is_singleton(); }
+
+ inline bool
+ certainly(bool_set __b)
+ { return ! __b.contains(false); }
+
+ inline bool
+ possibly(bool_set __b)
+ { return __b.contains(true); }
+
+
+ // 20.2.3.3 bool_set set operations
+
+ inline bool_set
+ set_union(bool __s, bool_set __t)
+ { return bool_set(__s) | __t; }
+
+ inline bool_set
+ set_union(bool_set __s, bool __t)
+ { return __s | bool_set(__t); }
+
+ inline bool_set
+ set_union(bool_set __s, bool_set __t)
+ { return __s | __t; }
+
+ inline bool_set
+ set_intersection(bool __s, bool_set __t)
+ { return bool_set(__s) & __t; }
+
+ inline bool_set
+ set_intersection(bool_set __s, bool __t)
+ { return __s & bool_set(__t); }
+
+ inline bool_set
+ set_intersection(bool_set __s, bool_set __t)
+ { return __s & __t; }
+
+ inline bool_set
+ set_complement(bool_set __b)
+ { return ! __b; }
+
+
+ // 20.2.3.4 bool_set logical operators
+
+ inline bool_set
+ operator^(bool __s, bool_set __t)
+ { return bool_set(__s) ^ __t; }
+
+ inline bool_set
+ operator^(bool_set __s, bool __t)
+ { return __s ^ bool_set(__t); }
+
+ inline bool_set
+ operator|(bool __s, bool_set __t)
+ { return bool_set(__s) | __t; }
+
+ inline bool_set
+ operator|(bool_set __s, bool __t)
+ { return __s | bool_set(__t); }
+
+ inline bool_set
+ operator&(bool __s, bool_set __t)
+ { return bool_set(__s) & __t; }
+
+ inline bool_set
+ operator&(bool_set __s, bool __t)
+ { return __s & bool_set(__t); }
+
+
+ // 20.2.3.5 bool_set relational operators
+
+ inline bool_set
+ operator==(bool __s, bool_set __t)
+ { return bool_set(__s) == __t; }
+
+ inline bool_set
+ operator==(bool_set __s, bool __t)
+ { return __s == bool_set(__t); }
+
+ inline bool_set
+ operator!=(bool __s, bool_set __t)
+ { return ! (__s == __t); }
+
+ inline bool_set
+ operator!=(bool_set __s, bool __t)
+ { return ! (__s == __t); }
+
+ inline bool_set
+ operator!=(bool_set __s, bool_set __t)
+ { return ! (__s == __t); }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#include <tr2/bool_set.tcc>
+
+#endif // _GLIBCXX_TR2_BOOL_SET
diff --git a/libstdc++-v3/include/tr2/bool_set.tcc b/libstdc++-v3/include/tr2/bool_set.tcc
new file mode 100644
index 00000000000..f24d4482398
--- /dev/null
+++ b/libstdc++-v3/include/tr2/bool_set.tcc
@@ -0,0 +1,277 @@
+// TR2 <bool_set> support files -*- C++ -*-
+
+// Copyright (C) 2009, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file tr2/bool_set.tcc
+ * This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_BOOL_SET_TCC
+#define _GLIBCXX_TR2_BOOL_SET_TCC 1
+
+#pragma GCC system_header
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ bool_set::_Bool_set_val
+ bool_set::_S_not[4] =
+ { _S_true_, _S_false, _S_indet, _S_empty };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_xor[4][4] =
+ { { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_true_, _S_false, _S_indet, _S_empty },
+ { _S_indet, _S_indet, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_or[4][4] =
+ { { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_true_, _S_true_, _S_true_, _S_empty },
+ { _S_indet, _S_true_, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_and[4][4] =
+ { { _S_false, _S_false, _S_false, _S_empty },
+ { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_false, _S_indet, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_eq[4][4] =
+ { { _S_true_, _S_false, _S_indet, _S_empty },
+ { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_indet, _S_indet, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+// I object to these things.
+// The stuff in locale facets are for basic types.
+// I think we could hack operator<< and operator>>.
+
+ /**
+ * @brief Numeric parsing.
+ *
+ * Parses the input stream into the bool @a v. It does so by calling
+ * num_get::do_get().
+ *
+ * If ios_base::boolalpha is set, attempts to read
+ * ctype<CharT>::truename() or ctype<CharT>::falsename(). Sets
+ * @a v to true or false if successful. Sets err to
+ * ios_base::failbit if reading the string fails. Sets err to
+ * ios_base::eofbit if the stream is emptied.
+ *
+ * If ios_base::boolalpha is not set, proceeds as with reading a long,
+ * except if the value is 1, sets @a v to true, if the value is 0, sets
+ * @a v to false, and otherwise set err to ios_base::failbit.
+ *
+ * @param in Start of input stream.
+ * @param end End of input stream.
+ * @param io Source of locale and flags.
+ * @param err Error flags to set.
+ * @param v Value to format and insert.
+ * @return Iterator after reading.
+ iter_type
+ get(iter_type __in, iter_type __end, ios_base& __io,
+ ios_base::iostate& __err, bool& __v) const
+ { return this->do_get(__in, __end, __io, __err, __v); }
+ */
+/*
+ template<typename _CharT, typename _InIter>
+ _InIter
+ num_get<_CharT, _InIter>::
+ do_get(iter_type __beg, iter_type __end, ios_base& __io,
+ ios_base::iostate& __err, bool_set& __v) const
+ {
+ if (!(__io.flags() & ios_base::boolalpha))
+ {
+ // Parse bool values as long.
+ // NB: We can't just call do_get(long) here, as it might
+ // refer to a derived class.
+ long __l = -1;
+ __beg = _M_extract_int(__beg, __end, __io, __err, __l);
+ if (__c >= _S_false && __c < _S_empty)
+ __b._M_b = static_cast<_Bool_set_val>(__c);
+ else
+ {
+ // What should we do here?
+ __v = true;
+ __err = ios_base::failbit;
+ if (__beg == __end)
+ __err |= ios_base::eofbit;
+ }
+ }
+ else
+ {
+ // Parse bool values as alphanumeric.
+ typedef __numpunct_cache<_CharT> __cache_type;
+ __use_cache<__cache_type> __uc;
+ const locale& __loc = __io._M_getloc();
+ const __cache_type* __lc = __uc(__loc);
+
+ bool __testf = true;
+ bool __testt = true;
+ bool __donef = __lc->_M_falsename_size == 0;
+ bool __donet = __lc->_M_truename_size == 0;
+ bool __testeof = false;
+ size_t __n = 0;
+ while (!__donef || !__donet)
+ {
+ if (__beg == __end)
+ {
+ __testeof = true;
+ break;
+ }
+
+ const char_type __c = *__beg;
+
+ if (!__donef)
+ __testf = __c == __lc->_M_falsename[__n];
+
+ if (!__testf && __donet)
+ break;
+
+ if (!__donet)
+ __testt = __c == __lc->_M_truename[__n];
+
+ if (!__testt && __donef)
+ break;
+
+ if (!__testt && !__testf)
+ break;
+
+ ++__n;
+ ++__beg;
+
+ __donef = !__testf || __n >= __lc->_M_falsename_size;
+ __donet = !__testt || __n >= __lc->_M_truename_size;
+ }
+ if (__testf && __n == __lc->_M_falsename_size && __n)
+ {
+ __v = false;
+ if (__testt && __n == __lc->_M_truename_size)
+ __err = ios_base::failbit;
+ else
+ __err = __testeof ? ios_base::eofbit : ios_base::goodbit;
+ }
+ else if (__testt && __n == __lc->_M_truename_size && __n)
+ {
+ __v = true;
+ __err = __testeof ? ios_base::eofbit : ios_base::goodbit;
+ }
+ else
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 23. Num_get overflow result.
+ __v = false;
+ __err = ios_base::failbit;
+ if (__testeof)
+ __err |= ios_base::eofbit;
+ }
+ }
+ return __beg;
+ }
+*/
+
+ /**
+ * @brief Numeric formatting.
+ *
+ * Formats the boolean @a v and inserts it into a stream. It does so
+ * by calling num_put::do_put().
+ *
+ * If ios_base::boolalpha is set, writes ctype<CharT>::truename() or
+ * ctype<CharT>::falsename(). Otherwise formats @a v as an int.
+ *
+ * @param s Stream to write to.
+ * @param io Source of locale and flags.
+ * @param fill Char_type to use for filling.
+ * @param v Value to format and insert.
+ * @return Iterator after writing.
+ iter_type
+ put(iter_type __s, ios_base& __f, char_type __fill, bool __v) const
+ { return this->do_put(__s, __f, __fill, __v); }
+ */
+
+/*
+ template<typename _CharT, typename _OutIter>
+ _OutIter
+ num_put<_CharT, _OutIter>::
+ do_put(iter_type __s, ios_base& __io, char_type __fill, bool_set __v) const
+ {
+ const ios_base::fmtflags __flags = __io.flags();
+ if ((__flags & ios_base::boolalpha) == 0)
+ {
+ const long __l = __v;
+ __s = _M_insert_int(__s, __io, __fill, __l);
+ }
+ else
+ {
+ typedef __numpunct_cache<_CharT> __cache_type;
+ __use_cache<__cache_type> __uc;
+ const locale& __loc = __io._M_getloc();
+ const __cache_type* __lc = __uc(__loc);
+
+ const _CharT* __name = __v ? __lc->_M_truename
+ : __lc->_M_falsename;
+ int __len = __v ? __lc->_M_truename_size
+ : __lc->_M_falsename_size;
+
+ const streamsize __w = __io.width();
+ if (__w > static_cast<streamsize>(__len))
+ {
+ const streamsize __plen = __w - __len;
+ _CharT* __ps
+ = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __plen));
+
+ char_traits<_CharT>::assign(__ps, __plen, __fill);
+ __io.width(0);
+
+ if ((__flags & ios_base::adjustfield) == ios_base::left)
+ {
+ __s = std::__write(__s, __name, __len);
+ __s = std::__write(__s, __ps, __plen);
+ }
+ else
+ {
+ __s = std::__write(__s, __ps, __plen);
+ __s = std::__write(__s, __name, __len);
+ }
+ return __s;
+ }
+ __io.width(0);
+ __s = std::__write(__s, __name, __len);
+ }
+ return __s;
+ }
+*/
+
+#endif // _GLIBCXX_TR2_BOOL_SET_TCC
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset
new file mode 100644
index 00000000000..5a4b7943bbe
--- /dev/null
+++ b/libstdc++-v3/include/tr2/dynamic_bitset
@@ -0,0 +1,1472 @@
+// TR2 <dynamic_bitset> -*- C++ -*-
+
+// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file tr2/dynamic_bitset
+ * This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_DYNAMIC_BITSET
+#define _GLIBCXX_TR2_DYNAMIC_BITSET 1
+
+#pragma GCC system_header
+
+#include <limits>
+#include <vector>
+#include <cstddef> // For size_t
+#include <string>
+#include <memory> // For std::allocator
+#include <bits/functexcept.h> // For invalid_argument, out_of_range,
+ // overflow_error
+#include <iosfwd>
+#include <cxxabi_forced.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * Dynamic Bitset.
+ *
+ * See N2050,
+ * Proposal to Add a Dynamically Sizeable Bitset to the Standard Library.
+ */
+namespace __detail
+{
+
+template<typename T>
+class _Bool2UChar
+{
+ typedef T type;
+};
+
+template<>
+class _Bool2UChar<bool>
+{
+public:
+ typedef unsigned char type;
+};
+
+}
+
+ /**
+ * Base class, general case.
+ *
+ * See documentation for dynamic_bitset.
+ */
+ template<typename _WordT = unsigned long long,
+ typename _Alloc = std::allocator<_WordT>>
+ struct __dynamic_bitset_base
+ {
+ static_assert(std::is_unsigned<_WordT>::value, "template argument "
+ "_WordT not an unsigned integral type");
+
+ typedef _WordT block_type;
+ typedef _Alloc allocator_type;
+ typedef size_t size_type;
+
+ static const size_type _S_bits_per_block = __CHAR_BIT__ * sizeof(block_type);
+ static const size_type npos = static_cast<size_type>(-1);
+
+ /// 0 is the least significant word.
+ std::vector<block_type, allocator_type> _M_w;
+
+ explicit
+ __dynamic_bitset_base(const allocator_type& __alloc = allocator_type())
+ : _M_w(__alloc)
+ { }
+
+ explicit
+ __dynamic_bitset_base(__dynamic_bitset_base&& __b)
+ { this->_M_w.swap(__b._M_w); }
+
+ explicit
+ __dynamic_bitset_base(size_type __nbits, unsigned long long __val = 0ULL,
+ const allocator_type& __alloc = allocator_type())
+ : _M_w(__nbits / _S_bits_per_block
+ + (__nbits % _S_bits_per_block > 0),
+ __val, __alloc)
+ {
+ unsigned long long __mask = ~static_cast<block_type>(0);
+ size_t __n = std::min(this->_M_w.size(),
+ sizeof(unsigned long long) / sizeof(block_type));
+ for (size_t __i = 0; __i < __n; ++__i)
+ {
+ this->_M_w[__i] = (__val & __mask) >> (__i * _S_bits_per_block);
+ __mask <<= _S_bits_per_block;
+ }
+ }
+
+ void
+ _M_assign(const __dynamic_bitset_base<block_type, allocator_type>& __b)
+ { this->_M_w = __b._M_w; }
+
+ void
+ _M_swap(__dynamic_bitset_base<block_type, allocator_type>& __b)
+ { this->_M_w.swap(__b._M_w); }
+
+ void
+ _M_clear()
+ { this->_M_w.clear(); }
+
+ void
+ _M_resize(size_t __nbits, bool __value)
+ {
+ size_t __sz = __nbits / _S_bits_per_block;
+ if (__nbits % _S_bits_per_block > 0)
+ ++__sz;
+ if (__sz != this->_M_w.size())
+ this->_M_w.resize(__sz);
+ }
+
+ allocator_type
+ _M_get_allocator() const
+ { return this->_M_w.get_allocator(); }
+
+ static size_type
+ _S_whichword(size_type __pos)
+ { return __pos / _S_bits_per_block; }
+
+ static size_type
+ _S_whichbyte(size_type __pos)
+ { return (__pos % _S_bits_per_block) / __CHAR_BIT__; }
+
+ static size_type
+ _S_whichbit(size_type __pos)
+ { return __pos % _S_bits_per_block; }
+
+ static block_type
+ _S_maskbit(size_type __pos)
+ { return (static_cast<block_type>(1)) << _S_whichbit(__pos); }
+
+ block_type&
+ _M_getword(size_type __pos)
+ { return this->_M_w[_S_whichword(__pos)]; }
+
+ block_type
+ _M_getword(size_type __pos) const
+ { return this->_M_w[_S_whichword(__pos)]; }
+
+ block_type&
+ _M_hiword()
+ { return this->_M_w[_M_w.size() - 1]; }
+
+ block_type
+ _M_hiword() const
+ { return this->_M_w[_M_w.size() - 1]; }
+
+ void
+ _M_do_and(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] &= __x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_or(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] |= __x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_xor(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] ^= __x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_dif(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] &= ~__x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_left_shift(size_t __shift);
+
+ void
+ _M_do_right_shift(size_t __shift);
+
+ void
+ _M_do_flip()
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] = ~this->_M_w[__i];
+ }
+
+ void
+ _M_do_set()
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] = ~static_cast<block_type>(0);
+ }
+
+ void
+ _M_do_reset()
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] = static_cast<block_type>(0);
+ }
+
+ bool
+ _M_is_equal(const __dynamic_bitset_base<block_type, allocator_type>& __x) const
+ {
+ if (__x.size() == this->size())
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i] != __x._M_w[__i])
+ return false;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ bool
+ _M_is_less(const __dynamic_bitset_base<block_type, allocator_type>& __x) const
+ {
+ if (__x.size() == this->size())
+ {
+ for (size_t __i = this->_M_w.size(); __i > 0; --__i)
+ {
+ if (this->_M_w[__i-1] < __x._M_w[__i-1])
+ return true;
+ else if (this->_M_w[__i-1] > __x._M_w[__i-1])
+ return false;
+ }
+ return false;
+ }
+ else
+ return false;
+ }
+
+ size_t
+ _M_are_all_aux() const
+ {
+ for (size_t __i = 0; __i < this->_M_w.size() - 1; ++__i)
+ if (_M_w[__i] != ~static_cast<block_type>(0))
+ return 0;
+ return ((this->_M_w.size() - 1) * _S_bits_per_block
+ + __builtin_popcountl(this->_M_hiword()));
+ }
+
+ bool
+ _M_is_any() const
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i] != static_cast<block_type>(0))
+ return true;
+ return false;
+ }
+
+ bool
+ _M_is_subset_of(const __dynamic_bitset_base<block_type, allocator_type>& __b)
+ {
+ if (__b.size() == this->size())
+ {
+ for (size_t __i = 0; __i < _M_w.size(); ++__i)
+ if (this->_M_w[__i] != (this->_M_w[__i] | __b._M_w[__i]))
+ return false;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ bool
+ _M_is_proper_subset_of(const __dynamic_bitset_base<block_type, allocator_type>& __b) const
+ {
+ if (this->is_subset_of(__b))
+ {
+ if (*this == __b)
+ return false;
+ else
+ return true;
+ }
+ else
+ return false;
+ }
+
+ size_t
+ _M_do_count() const
+ {
+ size_t __result = 0;
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ __result += __builtin_popcountl(this->_M_w[__i]);
+ return __result;
+ }
+
+ size_type
+ _M_size() const
+ { return this->_M_w.size(); }
+
+ unsigned long
+ _M_do_to_ulong() const;
+
+ unsigned long long
+ _M_do_to_ullong() const;
+
+ // find first "on" bit
+ size_type
+ _M_do_find_first(size_t __not_found) const;
+
+ // find the next "on" bit that follows "prev"
+ size_type
+ _M_do_find_next(size_t __prev, size_t __not_found) const;
+
+ // do append of block
+ void
+ _M_do_append_block(block_type __block, size_type __pos)
+ {
+ size_t __offset = __pos % _S_bits_per_block;
+ if (__offset == 0)
+ this->_M_w.push_back(__block);
+ else
+ {
+ this->_M_hiword() |= (__block << __offset);
+ this->_M_w.push_back(__block >> (_S_bits_per_block - __offset));
+ }
+ }
+ };
+
+ // Definitions of non-inline functions from __dynamic_bitset_base.
+ template<typename _WordT, typename _Alloc>
+ void
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_left_shift(size_t __shift)
+ {
+ if (__builtin_expect(__shift != 0, 1))
+ {
+ const size_t __wshift = __shift / _S_bits_per_block;
+ const size_t __offset = __shift % _S_bits_per_block;
+
+ if (__offset == 0)
+ for (size_t __n = this->_M_w.size() - 1; __n >= __wshift; --__n)
+ this->_M_w[__n] = this->_M_w[__n - __wshift];
+ else
+ {
+ const size_t __sub_offset = _S_bits_per_block - __offset;
+ for (size_t __n = _M_w.size() - 1; __n > __wshift; --__n)
+ this->_M_w[__n] = ((this->_M_w[__n - __wshift] << __offset)
+ | (this->_M_w[__n - __wshift - 1] >> __sub_offset));
+ this->_M_w[__wshift] = this->_M_w[0] << __offset;
+ }
+
+ ////std::fill(this->_M_w.begin(), this->_M_w.begin() + __wshift,
+ //// static_cast<_WordT>(0));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ void
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_right_shift(size_t __shift)
+ {
+ if (__builtin_expect(__shift != 0, 1))
+ {
+ const size_t __wshift = __shift / _S_bits_per_block;
+ const size_t __offset = __shift % _S_bits_per_block;
+ const size_t __limit = this->_M_w.size() - __wshift - 1;
+
+ if (__offset == 0)
+ for (size_t __n = 0; __n <= __limit; ++__n)
+ this->_M_w[__n] = this->_M_w[__n + __wshift];
+ else
+ {
+ const size_t __sub_offset = (_S_bits_per_block
+ - __offset);
+ for (size_t __n = 0; __n < __limit; ++__n)
+ this->_M_w[__n] = ((this->_M_w[__n + __wshift] >> __offset)
+ | (this->_M_w[__n + __wshift + 1] << __sub_offset));
+ this->_M_w[__limit] = this->_M_w[_M_w.size()-1] >> __offset;
+ }
+
+ ////std::fill(this->_M_w.begin() + __limit + 1, this->_M_w.end(),
+ //// static_cast<_WordT>(0));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ unsigned long
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ulong() const
+ {
+ size_t __n = sizeof(unsigned long) / sizeof(block_type);
+ for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i])
+ __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ulong"));
+ unsigned long __res = 0UL;
+ for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+ __res += this->_M_w[__i] << (__i * _S_bits_per_block);
+ return __res;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ unsigned long long
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ullong() const
+ {
+ size_t __n = sizeof(unsigned long long) / sizeof(block_type);
+ for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i])
+ __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ullong"));
+ unsigned long long __res = 0ULL;
+ for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+ __res += this->_M_w[__i] << (__i * _S_bits_per_block);
+ return __res;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ size_t
+ __dynamic_bitset_base<_WordT, _Alloc>
+ ::_M_do_find_first(size_t __not_found) const
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ {
+ _WordT __thisword = this->_M_w[__i];
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzl(__thisword));
+ }
+ // not found, so return an indication of failure.
+ return __not_found;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ size_t
+ __dynamic_bitset_base<_WordT, _Alloc>
+ ::_M_do_find_next(size_t __prev, size_t __not_found) const
+ {
+ // make bound inclusive
+ ++__prev;
+
+ // check out of bounds
+ if (__prev >= this->_M_w.size() * _S_bits_per_block)
+ return __not_found;
+
+ // search first word
+ size_t __i = _S_whichword(__prev);
+ _WordT __thisword = this->_M_w[__i];
+
+ // mask off bits below bound
+ __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev);
+
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzl(__thisword));
+
+ // check subsequent words
+ for (++__i; __i < this->_M_w.size(); ++__i)
+ {
+ __thisword = this->_M_w[__i];
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzl(__thisword));
+ }
+ // not found, so return an indication of failure.
+ return __not_found;
+ } // end _M_do_find_next
+
+ /**
+ * @brief The %dynamic_bitset class represents a sequence of bits.
+ *
+ * @ingroup containers
+ *
+ * (Note that %dynamic_bitset does @e not meet the formal
+ * requirements of a <a href="tables.html#65">container</a>.
+ * Mainly, it lacks iterators.)
+ *
+ * The template argument, @a Nb, may be any non-negative number,
+ * specifying the number of bits (e.g., "0", "12", "1024*1024").
+ *
+ * In the general unoptimized case, storage is allocated in
+ * word-sized blocks. Let B be the number of bits in a word, then
+ * (Nb+(B-1))/B words will be used for storage. B - Nb%B bits are
+ * unused. (They are the high-order bits in the highest word.) It
+ * is a class invariant that those unused bits are always zero.
+ *
+ * If you think of %dynamic_bitset as "a simple array of bits," be
+ * aware that your mental picture is reversed: a %dynamic_bitset
+ * behaves the same way as bits in integers do, with the bit at
+ * index 0 in the "least significant / right-hand" position, and
+ * the bit at index Nb-1 in the "most significant / left-hand"
+ * position. Thus, unlike other containers, a %dynamic_bitset's
+ * index "counts from right to left," to put it very loosely.
+ *
+ * This behavior is preserved when translating to and from strings.
+ * For example, the first line of the following program probably
+ * prints "b('a') is 0001100001" on a modern ASCII system.
+ *
+ * @code
+ * #include <dynamic_bitset>
+ * #include <iostream>
+ * #include <sstream>
+ *
+ * using namespace std;
+ *
+ * int main()
+ * {
+ * long a = 'a';
+ * dynamic_bitset b(a);
+ *
+ * cout << "b('a') is " << b << endl;
+ *
+ * ostringstream s;
+ * s << b;
+ * string str = s.str();
+ * cout << "index 3 in the string is " << str[3] << " but\n"
+ * << "index 3 in the bitset is " << b[3] << endl;
+ * }
+ * @endcode
+ *
+ * Also see:
+ * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch33s02.html
+ * for a description of extensions.
+ *
+ * Most of the actual code isn't contained in %dynamic_bitset<>
+ * itself, but in the base class __dynamic_bitset_base. The base
+ * class works with whole words, not with individual bits. This
+ * allows us to specialize __dynamic_bitset_base for the important
+ * special case where the %dynamic_bitset is only a single word.
+ *
+ * Extra confusion can result due to the fact that the storage for
+ * __dynamic_bitset_base @e is a vector, and is indexed as such. This is
+ * carefully encapsulated.
+ */
+ template<typename _WordT = unsigned long long,
+ typename _Alloc = std::allocator<_WordT>>
+ class dynamic_bitset
+ : private __dynamic_bitset_base<_WordT, _Alloc>
+ {
+ static_assert(std::is_unsigned<_WordT>::value, "template argument "
+ "_WordT not an unsigned integral type");
+
+ public:
+
+ typedef __dynamic_bitset_base<_WordT, _Alloc> _Base;
+ typedef _WordT block_type;
+ typedef _Alloc allocator_type;
+ typedef size_t size_type;
+
+ static const size_type bits_per_block = __CHAR_BIT__ * sizeof(block_type);
+ // Use this: constexpr size_type std::numeric_limits<size_type>::max().
+ static const size_type npos = static_cast<size_type>(-1);
+
+ private:
+
+ // Clear the unused bits in the uppermost word.
+ void
+ _M_do_sanitize()
+ {
+ size_type __shift = this->_M_Nb % bits_per_block;
+ if (__shift > 0)
+ this->_M_hiword() &= ~((~static_cast<block_type>(0)) << __shift);
+ }
+
+ /**
+ * These versions of single-bit set, reset, flip, and test
+ * do no range checking.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_set(size_type __pos)
+ {
+ this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_set(size_type __pos, int __val)
+ {
+ if (__val)
+ this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
+ else
+ this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_reset(size_type __pos)
+ {
+ this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_flip(size_type __pos)
+ {
+ this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ bool
+ _M_unchecked_test(size_type __pos) const
+ { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos))
+ != static_cast<_WordT>(0)); }
+
+ size_type _M_Nb;
+
+ public:
+ /**
+ * This encapsulates the concept of a single bit. An instance
+ * of this class is a proxy for an actual bit; this way the
+ * individual bit operations are done as faster word-size
+ * bitwise instructions.
+ *
+ * Most users will never need to use this class directly;
+ * conversions to and from bool are automatic and should be
+ * transparent. Overloaded operators help to preserve the
+ * illusion.
+ *
+ * (On a typical system, this "bit %reference" is 64 times the
+ * size of an actual bit. Ha.)
+ */
+ class reference
+ {
+ friend class dynamic_bitset;
+
+ block_type *_M_wp;
+ size_type _M_bpos;
+
+ // left undefined
+ reference();
+
+ public:
+ reference(dynamic_bitset& __b, size_type __pos)
+ {
+ this->_M_wp = &__b._M_getword(__pos);
+ this->_M_bpos = _Base::_S_whichbit(__pos);
+ }
+
+ ~reference()
+ { }
+
+ // For b[i] = __x;
+ reference&
+ operator=(bool __x)
+ {
+ if (__x)
+ *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
+ else
+ *this->_M_wp &= ~_Base::_S_maskbit(this->_M_bpos);
+ return *this;
+ }
+
+ // For b[i] = b[__j];
+ reference&
+ operator=(const reference& __j)
+ {
+ if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos)))
+ *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
+ else
+ *this->_M_wp &= ~_Base::_S_maskbit(this->_M_bpos);
+ return *this;
+ }
+
+ // Flips the bit
+ bool
+ operator~() const
+ { return (*(_M_wp) & _Base::_S_maskbit(this->_M_bpos)) == 0; }
+
+ // For __x = b[i];
+ operator bool() const
+ { return (*(this->_M_wp) & _Base::_S_maskbit(this->_M_bpos)) != 0; }
+
+ // For b[i].flip();
+ reference&
+ flip()
+ {
+ *this->_M_wp ^= _Base::_S_maskbit(this->_M_bpos);
+ return *this;
+ }
+ };
+
+ friend class reference;
+
+ typedef bool const_reference;
+
+ // 23.3.5.1 constructors:
+ /// All bits set to zero.
+ explicit
+ dynamic_bitset(const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc), _M_Nb(0)
+ { }
+
+ /// Initial bits bitwise-copied from a single word (others set to zero).
+ explicit
+ dynamic_bitset(size_type __nbits, unsigned long long __val = 0ULL,
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__nbits, __val, __alloc),
+ _M_Nb(__nbits)
+ { }
+
+ dynamic_bitset(initializer_list<block_type> __il,
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc), _M_Nb(0)
+ { this->append(__il); }
+
+ /**
+ * @brief Use a subset of a string.
+ * @param str A string of '0' and '1' characters.
+ * @param pos Index of the first character in @a s to use.
+ * @param n The number of characters to copy.
+ * @throw std::out_of_range If @a pos is bigger the size of @a s.
+ * @throw std::invalid_argument If a character appears in the string
+ * which is neither '0' nor '1'.
+ */
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ explicit
+ dynamic_bitset(const std::basic_string<_CharT, _Traits, _Alloc1>& __str,
+ typename basic_string<_CharT,_Traits,_Alloc1>::size_type
+ __pos = 0,
+ typename basic_string<_CharT,_Traits,_Alloc1>::size_type
+ __n = std::basic_string<_CharT, _Traits, _Alloc1>::npos,
+ _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'),
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc),
+ _M_Nb(0) // Watch for npos.
+ {
+ if (__pos > __str.size())
+ __throw_out_of_range(__N("dynamic_bitset::bitset initial position "
+ "not valid"));
+
+ // Watch for npos.
+ this->_M_Nb = (__n > __str.size() ? __str.size() - __pos : __n);
+ this->resize(this->_M_Nb);
+ this->_M_copy_from_string(__str, __pos, __n,
+ _CharT('0'), _CharT('1'));
+ }
+
+ /**
+ * @brief Construct from a string.
+ * @param str A string of '0' and '1' characters.
+ * @throw std::invalid_argument If a character appears in the string
+ * which is neither '0' nor '1'.
+ */
+ explicit
+ dynamic_bitset(const char* __str,
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc)
+ {
+ size_t __len = 0;
+ if (__str)
+ while (__str[__len] != '\0')
+ ++__len;
+ this->resize(__len);
+ this->_M_copy_from_ptr<char,std::char_traits<char>>
+ (__str, __len, 0, __len, '0', '1');
+ }
+
+ /**
+ * @brief Copy constructor.
+ */
+ dynamic_bitset(const dynamic_bitset& __b)
+ : _Base(__b), _M_Nb(__b.size())
+ { }
+
+ /**
+ * @brief Move constructor.
+ */
+ dynamic_bitset(dynamic_bitset&& __b)
+ : _Base(std::forward<_Base>(__b)), _M_Nb(__b.size())
+ { }
+
+ /**
+ * @brief Swap with another bitset.
+ */
+ void
+ swap(dynamic_bitset& __b)
+ {
+ this->_M_swap(__b);
+ std::swap(this->_M_Nb, __b._M_Nb);
+ }
+
+ /**
+ * @brief Assignment.
+ */
+ dynamic_bitset&
+ operator=(const dynamic_bitset& __b)
+ {
+ if (&__b != this)
+ {
+ this->_M_assign(__b);
+ this->_M_Nb = __b._M_Nb;
+ }
+ }
+
+ /**
+ * @brief Move assignment.
+ */
+ dynamic_bitset&
+ operator=(dynamic_bitset&& __b)
+ {
+ this->swap(__b);
+ return *this;
+ }
+
+ /**
+ * @brief Return the allocator for the bitset.
+ */
+ allocator_type
+ get_allocator() const
+ { return this->_M_get_allocator(); }
+
+ /**
+ * @brief Resize the bitset.
+ */
+ void
+ resize(size_type __nbits, bool __value = false)
+ {
+ this->_M_resize(__nbits, __value);
+ this->_M_Nb = __nbits;
+ this->_M_do_sanitize();
+ }
+
+ /**
+ * @brief Clear the bitset.
+ */
+ void
+ clear()
+ {
+ this->_M_clear();
+ this->_M_Nb = 0;
+ }
+
+ /**
+ * @brief Push a bit onto the high end of the bitset.
+ */
+ void
+ push_back(bool __bit)
+ {
+ if (size_t __offset = this->size() % bits_per_block == 0)
+ this->_M_do_append_block(block_type(0), this->_M_Nb);
+ ++this->_M_Nb;
+ this->_M_unchecked_set(this->_M_Nb, __bit);
+ }
+
+ /**
+ * @brief Append a block.
+ */
+ void
+ append(block_type __block)
+ {
+ this->_M_do_append_block(__block, this->_M_Nb);
+ this->_M_Nb += bits_per_block;
+ }
+
+ /**
+ * @brief
+ */
+ void
+ append(initializer_list<block_type> __il)
+ { this->append(__il.begin(), __il.end()); }
+
+ /**
+ * @brief Append an iterator range of blocks.
+ */
+ template <typename _BlockInputIterator>
+ void
+ append(_BlockInputIterator __first, _BlockInputIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ this->append(*__first);
+ }
+
+ // 23.3.5.2 dynamic_bitset operations:
+ //@{
+ /**
+ * @brief Operations on dynamic_bitsets.
+ * @param rhs A same-sized dynamic_bitset.
+ *
+ * These should be self-explanatory.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ operator&=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_and(__rhs);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator&=(dynamic_bitset<_WordT, _Alloc>&& __rhs)
+ {
+ this->_M_do_and(std::move(__rhs));
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator|=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_or(__rhs);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator^=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_xor(__rhs);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator-=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_dif(__rhs);
+ return *this;
+ }
+ //@}
+
+ //@{
+ /**
+ * @brief Operations on dynamic_bitsets.
+ * @param position The number of places to shift.
+ *
+ * These should be self-explanatory.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ operator<<=(size_type __pos)
+ {
+ if (__builtin_expect(__pos < this->_M_Nb, 1))
+ {
+ this->_M_do_left_shift(__pos);
+ this->_M_do_sanitize();
+ }
+ else
+ this->_M_do_reset();
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator>>=(size_type __pos)
+ {
+ if (__builtin_expect(__pos < this->_M_Nb, 1))
+ {
+ this->_M_do_right_shift(__pos);
+ this->_M_do_sanitize();
+ }
+ else
+ this->_M_do_reset();
+ return *this;
+ }
+ //@}
+
+ // Set, reset, and flip.
+ /**
+ * @brief Sets every bit to true.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ set()
+ {
+ this->_M_do_set();
+ this->_M_do_sanitize();
+ return *this;
+ }
+
+ /**
+ * @brief Sets a given bit to a particular value.
+ * @param position The index of the bit.
+ * @param val Either true or false, defaults to true.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ set(size_type __pos, bool __val = true)
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::set"));
+ return this->_M_unchecked_set(__pos, __val);
+ }
+
+ /**
+ * @brief Sets every bit to false.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ reset()
+ {
+ this->_M_do_reset();
+ return *this;
+ }
+
+ /**
+ * @brief Sets a given bit to false.
+ * @param position The index of the bit.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ *
+ * Same as writing @c set(pos,false).
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ reset(size_type __pos)
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::reset"));
+ return this->_M_unchecked_reset(__pos);
+ }
+
+ /**
+ * @brief Toggles every bit to its opposite value.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ flip()
+ {
+ this->_M_do_flip();
+ this->_M_do_sanitize();
+ return *this;
+ }
+
+ /**
+ * @brief Toggles a given bit to its opposite value.
+ * @param position The index of the bit.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ flip(size_type __pos)
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::flip"));
+ return this->_M_unchecked_flip(__pos);
+ }
+
+ /// See the no-argument flip().
+ dynamic_bitset<_WordT, _Alloc>
+ operator~() const
+ { return dynamic_bitset<_WordT, _Alloc>(*this).flip(); }
+
+ //@{
+ /**
+ * @brief Array-indexing support.
+ * @param position Index into the %dynamic_bitset.
+ * @return A bool for a 'const %dynamic_bitset'. For non-const
+ * bitsets, an instance of the reference proxy class.
+ * @note These operators do no range checking and throw no
+ * exceptions, as required by DR 11 to the standard.
+ */
+ reference
+ operator[](size_type __pos)
+ { return reference(*this,__pos); }
+
+ const_reference
+ operator[](size_type __pos) const
+ { return _M_unchecked_test(__pos); }
+ //@}
+
+ /**
+ * @brief Returns a numerical interpretation of the %dynamic_bitset.
+ * @return The integral equivalent of the bits.
+ * @throw std::overflow_error If there are too many bits to be
+ * represented in an @c unsigned @c long.
+ */
+ unsigned long
+ to_ulong() const
+ { return this->_M_do_to_ulong(); }
+
+ /**
+ * @brief Returns a numerical interpretation of the %dynamic_bitset.
+ * @return The integral equivalent of the bits.
+ * @throw std::overflow_error If there are too many bits to be
+ * represented in an @c unsigned @c long.
+ */
+ unsigned long long
+ to_ullong() const
+ { return this->_M_do_to_ullong(); }
+
+ /**
+ * @brief Returns a character interpretation of the %dynamic_bitset.
+ * @return The string equivalent of the bits.
+ *
+ * Note the ordering of the bits: decreasing character positions
+ * correspond to increasing bit positions (see the main class notes for
+ * an example).
+ */
+ template<typename _CharT = char,
+ typename _Traits = std::char_traits<_CharT>,
+ typename _Alloc1 = std::allocator<_CharT>>
+ std::basic_string<_CharT, _Traits, _Alloc1>
+ to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const
+ {
+ std::basic_string<_CharT, _Traits, _Alloc1> __result;
+ _M_copy_to_string(__result, __zero, __one);
+ return __result;
+ }
+
+ // Helper functions for string operations.
+ template<typename _CharT, typename _Traits>
+ void
+ _M_copy_from_ptr(const _CharT*, size_t, size_t, size_t,
+ _CharT, _CharT);
+
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ void
+ _M_copy_from_string(const std::basic_string<_CharT,
+ _Traits, _Alloc1>& __str, size_t __pos, size_t __n,
+ _CharT __zero = _CharT('0'),
+ _CharT __one = _CharT('1'))
+ { _M_copy_from_ptr<_CharT, _Traits>(__str.data(), __str.size(),
+ __pos, __n, __zero, __one); }
+
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ void
+ _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str,
+ _CharT __zero = _CharT('0'),
+ _CharT __one = _CharT('1')) const;
+
+ /// Returns the number of bits which are set.
+ size_type
+ count() const
+ { return this->_M_do_count(); }
+
+ /// Returns the total number of bits.
+ size_type
+ size() const
+ { return this->_M_Nb; }
+
+ /// Returns the total number of blocks.
+ size_type num_blocks() const
+ { return this->_M_size(); }
+
+ /// Returns true if the dynamic_bitset is empty.
+ bool
+ empty() const
+ { return (this->_M_Nb == 0); }
+
+ /// Returns the maximum size of a dynamic_bitset object having the same
+ /// type as *this.
+ /// The real answer is max() * bits_per_block but is likely to overflow.
+ /*constexpr*/ size_type
+ max_size() const
+ { return std::numeric_limits<block_type>::max(); }
+
+ /**
+ * @brief Tests the value of a bit.
+ * @param position The index of a bit.
+ * @return The value at @a pos.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ */
+ bool
+ test(size_type __pos) const
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::test"));
+ return _M_unchecked_test(__pos);
+ }
+
+ /**
+ * @brief Tests whether all the bits are on.
+ * @return True if all the bits are set.
+ */
+ bool
+ all() const
+ { return this->_M_are_all_aux() == _M_Nb; }
+
+ /**
+ * @brief Tests whether any of the bits are on.
+ * @return True if at least one bit is set.
+ */
+ bool
+ any() const
+ { return this->_M_is_any(); }
+
+ /**
+ * @brief Tests whether any of the bits are on.
+ * @return True if none of the bits are set.
+ */
+ bool
+ none() const
+ { return !this->_M_is_any(); }
+
+ //@{
+ /// Self-explanatory.
+ dynamic_bitset<_WordT, _Alloc>
+ operator<<(size_type __pos) const
+ { return dynamic_bitset<_WordT, _Alloc>(*this) <<= __pos; }
+
+ dynamic_bitset<_WordT, _Alloc>
+ operator>>(size_type __pos) const
+ { return dynamic_bitset<_WordT, _Alloc>(*this) >>= __pos; }
+ //@}
+
+ /**
+ * @brief Finds the index of the first "on" bit.
+ * @return The index of the first bit set, or size() if not found.
+ * @sa find_next
+ */
+ size_type
+ find_first() const
+ { return this->_M_do_find_first(this->_M_Nb); }
+
+ /**
+ * @brief Finds the index of the next "on" bit after prev.
+ * @return The index of the next bit set, or size() if not found.
+ * @param prev Where to start searching.
+ * @sa find_first
+ */
+ size_type
+ find_next(size_t __prev) const
+ { return this->_M_do_find_next(__prev, this->_M_Nb); }
+
+ bool
+ is_subset_of(const dynamic_bitset& __b) const
+ { return this->_M_is_subset_of(__b); }
+
+ bool
+ is_proper_subset_of(const dynamic_bitset& __b) const
+ { return this->_M_is_proper_subset_of(__b); }
+ };
+
+ // Definitions of non-inline member functions.
+ template<typename _WordT, typename _Alloc>
+ template<typename _CharT, typename _Traits>
+ void
+ dynamic_bitset<_WordT, _Alloc>::
+ _M_copy_from_ptr(const _CharT* __str, size_t __len,
+ size_t __pos, size_t __n, _CharT __zero, _CharT __one)
+ {
+ reset();
+ const size_t __nbits = std::min(_M_Nb, std::min(__n, __len - __pos));
+ for (size_t __i = __nbits; __i > 0; --__i)
+ {
+ const _CharT __c = __str[__pos + __nbits - __i];
+ if (_Traits::eq(__c, __zero))
+ ;
+ else if (_Traits::eq(__c, __one))
+ _M_unchecked_set(__i - 1);
+ else
+ __throw_invalid_argument(__N("dynamic_bitset::_M_copy_from_ptr"));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ void
+ dynamic_bitset<_WordT, _Alloc>::
+ _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str,
+ _CharT __zero, _CharT __one) const
+ {
+ __str.assign(_M_Nb, __zero);
+ for (size_t __i = _M_Nb; __i > 0; --__i)
+ if (_M_unchecked_test(__i - 1))
+ _Traits::assign(__str[_M_Nb - __i], __one);
+ }
+
+
+ //@{
+ /// These comparisons for equality/inequality are, well, @e bitwise.
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __lhs._M_is_equal(__rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator!=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return !__lhs._M_is_equal(__rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __lhs._M_is_less(__rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator<=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return !(__lhs > __rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator>(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __rhs < __lhs; }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator>=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return !(__lhs < __rhs); }
+ //@}
+
+ // 23.3.5.3 bitset operations:
+ //@{
+ /**
+ * @brief Global bitwise operations on bitsets.
+ * @param x A bitset.
+ * @param y A bitset of the same size as @a x.
+ * @return A new bitset.
+ *
+ * These should be self-explanatory.
+ */
+ template<typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator&(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result &= __y;
+ return __result;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator|(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result |= __y;
+ return __result;
+ }
+
+ template <typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator^(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result ^= __y;
+ return __result;
+ }
+
+ template <typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator-(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result -= __y;
+ return __result;
+ }
+ //@}
+
+ //@{
+ /**
+ * @brief Global I/O operators for bitsets.
+ *
+ * Direct I/O between streams and bitsets is supported. Output is
+ * straightforward. Input will skip whitespace and only accept '0'
+ * and '1' characters. The %dynamic_bitset will grow as necessary
+ * to hold the string of bits.
+ */
+ template<typename _CharT, typename _Traits,
+ typename _WordT, typename _Alloc>
+ std::basic_istream<_CharT, _Traits>&
+ operator>>(std::basic_istream<_CharT, _Traits>& __is,
+ dynamic_bitset<_WordT, _Alloc>& __x)
+ {
+ typedef typename _Traits::char_type char_type;
+ typedef std::basic_istream<_CharT, _Traits> __istream_type;
+ typedef typename __istream_type::ios_base __ios_base;
+
+ std::basic_string<_CharT, _Traits> __tmp;
+ __tmp.reserve(__x.size());
+
+ const char_type __zero = __is.widen('0');
+ const char_type __one = __is.widen('1');
+
+ typename __ios_base::iostate __state = __ios_base::goodbit;
+ typename __istream_type::sentry __sentry(__is);
+ if (__sentry)
+ {
+ __try
+ {
+ while (1)
+ {
+ static typename _Traits::int_type __eof = _Traits::eof();
+
+ typename _Traits::int_type __c1 = __is.rdbuf()->sbumpc();
+ if (_Traits::eq_int_type(__c1, __eof))
+ {
+ __state |= __ios_base::eofbit;
+ break;
+ }
+ else
+ {
+ const char_type __c2 = _Traits::to_char_type(__c1);
+ if (_Traits::eq(__c2, __zero))
+ __tmp.push_back(__zero);
+ else if (_Traits::eq(__c2, __one))
+ __tmp.push_back(__one);
+ else if (_Traits::
+ eq_int_type(__is.rdbuf()->sputbackc(__c2),
+ __eof))
+ {
+ __state |= __ios_base::failbit;
+ break;
+ }
+ else
+ break;
+ }
+ }
+ }
+ __catch(__cxxabiv1::__forced_unwind&)
+ {
+ __is._M_setstate(__ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __is._M_setstate(__ios_base::badbit); }
+ }
+
+ __x.resize(__tmp.size());
+
+ if (__tmp.empty() && __x.size())
+ __state |= __ios_base::failbit;
+ else
+ __x._M_copy_from_string(__tmp, static_cast<size_t>(0), __x.size(),
+ __zero, __one);
+ if (__state)
+ __is.setstate(__state);
+ return __is;
+ }
+
+ template <typename _CharT, typename _Traits,
+ typename _WordT, typename _Alloc>
+ std::basic_ostream<_CharT, _Traits>&
+ operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+ const dynamic_bitset<_WordT, _Alloc>& __x)
+ {
+ std::basic_string<_CharT, _Traits> __tmp;
+
+ const ctype<_CharT>& __ct = use_facet<ctype<_CharT>>(__os.getloc());
+ __x._M_copy_to_string(__tmp, __ct.widen('0'), __ct.widen('1'));
+ return __os << __tmp;
+ }
+ //@}
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // tr2
+} // std
+
+#undef _GLIBCXX_BITSET_BITS_PER_WORD
+
+#endif /* _GLIBCXX_TR2_DYNAMIC_BITSET */
diff --git a/libstdc++-v3/include/tr2/ratio b/libstdc++-v3/include/tr2/ratio
new file mode 100644
index 00000000000..34a9553c444
--- /dev/null
+++ b/libstdc++-v3/include/tr2/ratio
@@ -0,0 +1,59 @@
+// TR2 <ratio> -*- C++ -*-
+
+// Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file tr2/ratio
+ * This is a TR2 C++ Library header.
+ */
+
+#include <ratio>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<intmax_t _Pn, size_t _Bit,
+ bool = _Bit < static_cast<size_t>
+ (std::numeric_limits<intmax_t>::digits)>
+ struct __safe_lshift
+ { static const intmax_t __value = 0; };
+
+ template<intmax_t _Pn, size_t _Bit>
+ struct __safe_lshift<_Pn, _Bit, true>
+ { static const intmax_t __value = _Pn << _Bit; };
+
+ /// Add binary prefixes (IEC 60027-2 A.2 and ISO/IEC 80000).
+ typedef ratio<__safe_lshift<1, 10>::__value, 1> kibi;
+ typedef ratio<__safe_lshift<1, 20>::__value, 1> mebi;
+ typedef ratio<__safe_lshift<1, 30>::__value, 1> gibi;
+ typedef ratio<__safe_lshift<1, 40>::__value, 1> tebi;
+ typedef ratio<__safe_lshift<1, 50>::__value, 1> pebi;
+ typedef ratio<__safe_lshift<1, 60>::__value, 1> exbi;
+ //typedef ratio<__safe_lshift<1, 70>::__value, 1> zebi;
+ //typedef ratio<__safe_lshift<1, 80>::__value, 1> yobi;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
diff --git a/libstdc++-v3/include/tr2/type_traits b/libstdc++-v3/include/tr2/type_traits
new file mode 100644
index 00000000000..73edf1137e4
--- /dev/null
+++ b/libstdc++-v3/include/tr2/type_traits
@@ -0,0 +1,102 @@
+// TR2 <type_traits> -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library 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/>.
+
+/** @file tr2/type_traits
+ * This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @defgroup metaprogramming Type Traits
+ * @ingroup utilities
+ *
+ * Compile time type transformation and information.
+ * @{
+ */
+
+ template<typename... _Elements>
+ struct typelist;
+
+ template<>
+ struct typelist<>
+ {
+ typedef std::true_type empty;
+ };
+
+ template<typename _First, typename... _Rest>
+ struct typelist<_First, _Rest...>
+ {
+ typedef std::false_type empty;
+
+ struct first
+ {
+ typedef _First type;
+ };
+
+ struct rest
+ {
+ typedef typelist<_Rest...> type;
+ };
+ };
+
+ // Sequence abstraction metafunctions default to looking in the type
+ template<typename _Tp>
+ struct first : public _Tp::first { };
+
+ template<typename _Tp>
+ struct rest : public _Tp::rest { };
+
+ template<typename _Tp>
+ struct empty : public _Tp::empty { };
+
+
+ template<typename _Tp>
+ struct bases
+ {
+ typedef typelist<__bases(_Tp)...> type;
+ };
+
+ template<typename _Tp>
+ struct direct_bases
+ {
+ typedef typelist<__direct_bases(_Tp)...> type;
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
diff --git a/libstdc++-v3/libsupc++/cxxabi.h b/libstdc++-v3/libsupc++/cxxabi.h
index 0f3856e7458..e78f551ed45 100644
--- a/libstdc++-v3/libsupc++/cxxabi.h
+++ b/libstdc++-v3/libsupc++/cxxabi.h
@@ -123,23 +123,26 @@ namespace __cxxabiv1
void
__cxa_guard_abort(__guard*) _GLIBCXX_NOTHROW;
+ // DSO destruction.
+ int
+ __cxa_atexit(void (*)(void*), void*, void*) _GLIBCXX_NOTHROW;
+
+ int
+ __cxa_finalize(void*);
+
// Pure virtual functions.
void
__cxa_pure_virtual(void) __attribute__ ((__noreturn__));
- // Exception handling.
void
- __cxa_bad_cast();
+ __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
- void
- __cxa_bad_typeid();
-
- // DSO destruction.
- int
- __cxa_atexit(void (*)(void*), void*, void*) _GLIBCXX_NOTHROW;
+ // Exception handling auxillary.
+ void
+ __cxa_bad_cast() __attribute__((__noreturn__));
- int
- __cxa_finalize(void*);
+ void
+ __cxa_bad_typeid() __attribute__((__noreturn__));
/**
@@ -185,6 +188,7 @@ namespace __cxxabiv1
char*
__cxa_demangle(const char* __mangled_name, char* __output_buffer,
size_t* __length, int* __status);
+
#ifdef __cplusplus
}
} // namespace __cxxabiv1
@@ -547,30 +551,89 @@ namespace __cxxabiv1
__upcast_result& __restrict __result) const;
};
+ // Exception handling forward declarations.
+ struct __cxa_exception;
+ struct __cxa_refcounted_exception;
+ struct __cxa_dependent_exception;
+ struct __cxa_eh_globals;
+
+ extern "C"
+ {
// Dynamic cast runtime.
+
// src2dst has the following possible values
// >-1: src_type is a unique public non-virtual base of dst_type
// dst_ptr + src2dst == src_ptr
// -1: unspecified relationship
// -2: src_type is not a public base of dst_type
// -3: src_type is a multiple public non-virtual base of dst_type
- extern "C" void*
+ void*
__dynamic_cast(const void* __src_ptr, // Starting object.
const __class_type_info* __src_type, // Static type of object.
const __class_type_info* __dst_type, // Desired target type.
ptrdiff_t __src2dst); // How src and dst are related.
+ // Exception handling runtime.
+
+ // The __cxa_eh_globals for the current thread can be obtained by using
+ // either of the following functions. The "fast" version assumes at least
+ // one prior call of __cxa_get_globals has been made from the current
+ // thread, so no initialization is necessary.
+ __cxa_eh_globals*
+ __cxa_get_globals() _GLIBCXX_NOTHROW __attribute__ ((__const__));
+
+ __cxa_eh_globals*
+ __cxa_get_globals_fast() _GLIBCXX_NOTHROW __attribute__ ((__const__));
+
+ // Allocate memory for the primary exception plus the thrown object.
+ void*
+ __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW;
+
+ // Free the space allocated for the primary exception.
+ void
+ __cxa_free_exception(void*) _GLIBCXX_NOTHROW;
+
+ // Throw the exception.
+ void
+ __cxa_throw(void*, std::type_info*, void (*) (void *))
+ __attribute__((__noreturn__));
+
+ // Used to implement exception handlers.
+ void*
+ __cxa_get_exception_ptr(void*) _GLIBCXX_NOTHROW __attribute__ ((__pure__));
+
+ void*
+ __cxa_begin_catch(void*) _GLIBCXX_NOTHROW;
+
+ void
+ __cxa_end_catch();
+
+ void
+ __cxa_rethrow() __attribute__((__noreturn__));
+
// Returns the type_info for the currently handled exception [15.3/8], or
// null if there is none.
- extern "C" std::type_info*
+ std::type_info*
__cxa_current_exception_type() _GLIBCXX_NOTHROW __attribute__ ((__pure__));
+ // GNU Extensions.
+
+ // Allocate memory for a dependent exception.
+ __cxa_dependent_exception*
+ __cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW;
+
+ // Free the space allocated for the dependent exception.
+ void
+ __cxa_free_dependent_exception(__cxa_dependent_exception*) _GLIBCXX_NOTHROW;
+
+ } // extern "C"
+
// A magic placeholder class that can be caught by reference
// to recognize foreign exceptions.
class __foreign_exception
{
- virtual ~__foreign_exception() _GLIBCXX_NOTHROW;
+ virtual ~__foreign_exception() throw();
virtual void __pure_dummy() = 0; // prevent catch by value
};
diff --git a/libstdc++-v3/libsupc++/del_op.cc b/libstdc++-v3/libsupc++/del_op.cc
index 86d4c1e2985..0d69aa3aa35 100644
--- a/libstdc++-v3/libsupc++/del_op.cc
+++ b/libstdc++-v3/libsupc++/del_op.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2007, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2007, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -41,7 +42,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete(void* ptr) throw ()
+operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT
{
if (ptr)
std::free(ptr);
diff --git a/libstdc++-v3/libsupc++/del_opnt.cc b/libstdc++-v3/libsupc++/del_opnt.cc
index 29eab1022ee..1a43ca4e789 100644
--- a/libstdc++-v3/libsupc++/del_opnt.cc
+++ b/libstdc++-v3/libsupc++/del_opnt.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -29,7 +30,7 @@
extern "C" void free (void *);
_GLIBCXX_WEAK_DEFINITION void
-operator delete (void *ptr, const std::nothrow_t&) throw ()
+operator delete (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
free (ptr);
}
diff --git a/libstdc++-v3/libsupc++/del_opv.cc b/libstdc++-v3/libsupc++/del_opv.cc
index c56df07d9d7..594f86262d7 100644
--- a/libstdc++-v3/libsupc++/del_opv.cc
+++ b/libstdc++-v3/libsupc++/del_opv.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr) throw ()
+operator delete[] (void *ptr) _GLIBCXX_USE_NOEXCEPT
{
::operator delete (ptr);
}
diff --git a/libstdc++-v3/libsupc++/del_opvnt.cc b/libstdc++-v3/libsupc++/del_opvnt.cc
index fec64953e63..e27eb5826e3 100644
--- a/libstdc++-v3/libsupc++/del_opvnt.cc
+++ b/libstdc++-v3/libsupc++/del_opvnt.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr, const std::nothrow_t&) throw ()
+operator delete[] (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
::operator delete (ptr);
}
diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc
index 818af0fe1f0..74474d82ec6 100644
--- a/libstdc++-v3/libsupc++/eh_alloc.cc
+++ b/libstdc++-v3/libsupc++/eh_alloc.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Allocate exception objects.
-// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2011
// Free Software Foundation, Inc.
//
// This file is part of GCC.
@@ -94,7 +94,7 @@ namespace
}
extern "C" void *
-__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
+__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW
{
void *ret;
@@ -139,7 +139,7 @@ __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
extern "C" void
-__cxxabiv1::__cxa_free_exception(void *vptr) throw()
+__cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW
{
char *base = (char *) emergency_buffer;
char *ptr = (char *) vptr;
@@ -158,7 +158,7 @@ __cxxabiv1::__cxa_free_exception(void *vptr) throw()
extern "C" __cxa_dependent_exception*
-__cxxabiv1::__cxa_allocate_dependent_exception() throw()
+__cxxabiv1::__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW
{
__cxa_dependent_exception *ret;
@@ -202,7 +202,7 @@ __cxxabiv1::__cxa_allocate_dependent_exception() throw()
extern "C" void
__cxxabiv1::__cxa_free_dependent_exception
- (__cxa_dependent_exception *vptr) throw()
+ (__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW
{
char *base = (char *) dependents_buffer;
char *ptr = (char *) vptr;
diff --git a/libstdc++-v3/libsupc++/eh_catch.cc b/libstdc++-v3/libsupc++/eh_catch.cc
index 567222aa5f0..b111497688d 100644
--- a/libstdc++-v3/libsupc++/eh_catch.cc
+++ b/libstdc++-v3/libsupc++/eh_catch.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Exception handling routines for catching.
-// Copyright (C) 2001, 2003, 2004, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2003, 2004, 2009, 2011 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -28,7 +28,7 @@
using namespace __cxxabiv1;
extern "C" void *
-__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) throw()
+__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) _GLIBCXX_NOTHROW
{
_Unwind_Exception *exceptionObject
= reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
@@ -37,7 +37,7 @@ __cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) throw()
}
extern "C" void *
-__cxxabiv1::__cxa_begin_catch (void *exc_obj_in) throw()
+__cxxabiv1::__cxa_begin_catch (void *exc_obj_in) _GLIBCXX_NOTHROW
{
_Unwind_Exception *exceptionObject
= reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
diff --git a/libstdc++-v3/libsupc++/eh_globals.cc b/libstdc++-v3/libsupc++/eh_globals.cc
index 63f46a99e0b..0c7f6b76088 100644
--- a/libstdc++-v3/libsupc++/eh_globals.cc
+++ b/libstdc++-v3/libsupc++/eh_globals.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Manage the thread-local exception globals.
-// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2011
// Free Software Foundation, Inc.
//
// This file is part of GCC.
@@ -47,7 +47,7 @@ using namespace __cxxabiv1;
namespace
{
abi::__cxa_eh_globals*
- get_global() throw()
+ get_global() _GLIBCXX_NOTHROW
{
static __thread abi::__cxa_eh_globals global;
return &global;
@@ -55,11 +55,11 @@ namespace
} // anonymous namespace
extern "C" __cxa_eh_globals*
-__cxxabiv1::__cxa_get_globals_fast() throw()
+__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
{ return get_global(); }
extern "C" __cxa_eh_globals*
-__cxxabiv1::__cxa_get_globals() throw()
+__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
{ return get_global(); }
@@ -110,7 +110,7 @@ struct __eh_globals_init
static __eh_globals_init init;
extern "C" __cxa_eh_globals*
-__cxxabiv1::__cxa_get_globals_fast() throw()
+__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
{
__cxa_eh_globals* g;
if (init._M_init)
@@ -121,7 +121,7 @@ __cxxabiv1::__cxa_get_globals_fast() throw()
}
extern "C" __cxa_eh_globals*
-__cxxabiv1::__cxa_get_globals() throw()
+__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
{
__cxa_eh_globals* g;
if (init._M_init)
@@ -148,11 +148,11 @@ __cxxabiv1::__cxa_get_globals() throw()
#else
extern "C" __cxa_eh_globals*
-__cxxabiv1::__cxa_get_globals_fast() throw()
+__cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
{ return &eh_globals; }
extern "C" __cxa_eh_globals*
-__cxxabiv1::__cxa_get_globals() throw()
+__cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
{ return &eh_globals; }
#endif
diff --git a/libstdc++-v3/libsupc++/eh_type.cc b/libstdc++-v3/libsupc++/eh_type.cc
index bb8be0b752e..245e0eaab96 100644
--- a/libstdc++-v3/libsupc++/eh_type.cc
+++ b/libstdc++-v3/libsupc++/eh_type.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Exception handling routines for catching.
-// Copyright (C) 2001, 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2008, 2009, 2011 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -33,7 +33,7 @@ namespace __cxxabiv1
// Returns the type_info for the currently handled exception [15.3/8], or
// null if there is none.
extern "C"
-std::type_info *__cxa_current_exception_type () throw()
+std::type_info *__cxa_current_exception_type () _GLIBCXX_NOTHROW
{
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 80ee3ba0fd8..1c258002e65 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -1,7 +1,7 @@
// The -*- C++ -*- dynamic memory management header.
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-// 2003, 2004, 2005, 2006, 2007, 2009, 2010
+// 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
// Free Software Foundation
// This file is part of GCC.
@@ -90,22 +90,32 @@ namespace std
* Placement new and delete signatures (take a memory address argument,
* does nothing) may not be replaced by a user's program.
*/
-void* operator new(std::size_t) throw (std::bad_alloc);
-void* operator new[](std::size_t) throw (std::bad_alloc);
-void operator delete(void*) throw();
-void operator delete[](void*) throw();
-void* operator new(std::size_t, const std::nothrow_t&) throw();
-void* operator new[](std::size_t, const std::nothrow_t&) throw();
-void operator delete(void*, const std::nothrow_t&) throw();
-void operator delete[](void*, const std::nothrow_t&) throw();
+void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
+ __attribute__((__externally_visible__));
+void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
+ __attribute__((__externally_visible__));
+void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
// Default placement versions of operator new.
-inline void* operator new(std::size_t, void* __p) throw() { return __p; }
-inline void* operator new[](std::size_t, void* __p) throw() { return __p; }
+inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
+{ return __p; }
+inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
+{ return __p; }
// Default placement versions of operator delete.
-inline void operator delete (void*, void*) throw() { }
-inline void operator delete[](void*, void*) throw() { }
+inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
+inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
//@}
} // extern "C++"
diff --git a/libstdc++-v3/libsupc++/new_op.cc b/libstdc++-v3/libsupc++/new_op.cc
index c61e941bcff..bb0199e969e 100644
--- a/libstdc++-v3/libsupc++/new_op.cc
+++ b/libstdc++-v3/libsupc++/new_op.cc
@@ -42,7 +42,7 @@ extern "C" void *malloc (std::size_t);
extern new_handler __new_handler;
_GLIBCXX_WEAK_DEFINITION void *
-operator new (std::size_t sz) throw (std::bad_alloc)
+operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
void *p;
diff --git a/libstdc++-v3/libsupc++/new_opnt.cc b/libstdc++-v3/libsupc++/new_opnt.cc
index 1bcdead5846..71600a63c3d 100644
--- a/libstdc++-v3/libsupc++/new_opnt.cc
+++ b/libstdc++-v3/libsupc++/new_opnt.cc
@@ -34,7 +34,7 @@ extern "C" void *malloc (std::size_t);
extern new_handler __new_handler;
_GLIBCXX_WEAK_DEFINITION void *
-operator new (std::size_t sz, const std::nothrow_t&) throw()
+operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
void *p;
diff --git a/libstdc++-v3/libsupc++/new_opv.cc b/libstdc++-v3/libsupc++/new_opv.cc
index b200e23c3ec..4080bd25b4f 100644
--- a/libstdc++-v3/libsupc++/new_opv.cc
+++ b/libstdc++-v3/libsupc++/new_opv.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void*
-operator new[] (std::size_t sz) throw (std::bad_alloc)
+operator new[] (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
return ::operator new(sz);
}
diff --git a/libstdc++-v3/libsupc++/new_opvnt.cc b/libstdc++-v3/libsupc++/new_opvnt.cc
index da4ae80b697..0609e687ab7 100644
--- a/libstdc++-v3/libsupc++/new_opvnt.cc
+++ b/libstdc++-v3/libsupc++/new_opvnt.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,8 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void*
-operator new[] (std::size_t sz, const std::nothrow_t& nothrow) throw()
+operator new[] (std::size_t sz, const std::nothrow_t& nothrow)
+ _GLIBCXX_USE_NOEXCEPT
{
return ::operator new(sz, nothrow);
}
diff --git a/libstdc++-v3/libsupc++/pure.cc b/libstdc++-v3/libsupc++/pure.cc
index acf72327a45..4879e59de35 100644
--- a/libstdc++-v3/libsupc++/pure.cc
+++ b/libstdc++-v3/libsupc++/pure.cc
@@ -1,5 +1,5 @@
// -*- C++ -*-
-// Copyright (C) 2000, 2001, 2009 Free Software Foundation
+// Copyright (C) 2000, 2001, 2009, 2011 Free Software Foundation
//
// This file is part of GCC.
//
@@ -49,3 +49,10 @@ __cxxabiv1::__cxa_pure_virtual (void)
writestr ("pure virtual method called\n");
std::terminate ();
}
+
+extern "C" void
+__cxxabiv1::__cxa_deleted_virtual (void)
+{
+ writestr ("deleted virtual method called\n");
+ std::terminate ();
+}
diff --git a/libstdc++-v3/libsupc++/unwind-cxx.h b/libstdc++-v3/libsupc++/unwind-cxx.h
index e62ea7c38be..84dd36781df 100644
--- a/libstdc++-v3/libsupc++/unwind-cxx.h
+++ b/libstdc++-v3/libsupc++/unwind-cxx.h
@@ -36,6 +36,7 @@
#include <cstddef>
#include "unwind.h"
#include <bits/atomic_word.h>
+#include <cxxabi.h>
#pragma GCC visibility push(default)
@@ -143,47 +144,6 @@ struct __cxa_eh_globals
#endif
};
-
-// The __cxa_eh_globals for the current thread can be obtained by using
-// either of the following functions. The "fast" version assumes at least
-// one prior call of __cxa_get_globals has been made from the current
-// thread, so no initialization is necessary.
-extern "C" __cxa_eh_globals *__cxa_get_globals () throw()
- __attribute__ ((__const__));
-extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw()
- __attribute__ ((__const__));
-
-// Allocate memory for the primary exception plus the thrown object.
-extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw();
-
-// Free the space allocated for the primary exception.
-extern "C" void __cxa_free_exception(void *thrown_exception) throw();
-
-// Allocate memory for a dependent exception.
-extern "C" __cxa_dependent_exception*
-__cxa_allocate_dependent_exception() throw();
-
-// Free the space allocated for the dependent exception.
-extern "C" void
-__cxa_free_dependent_exception(__cxa_dependent_exception *ex) throw();
-
-// Throw the exception.
-extern "C" void __cxa_throw (void *thrown_exception,
- std::type_info *tinfo,
- void (*dest) (void *))
- __attribute__((__noreturn__));
-
-// Used to implement exception handlers.
-extern "C" void *__cxa_get_exception_ptr (void *) throw()
- __attribute__ ((__pure__));
-extern "C" void *__cxa_begin_catch (void *) throw();
-extern "C" void __cxa_end_catch ();
-extern "C" void __cxa_rethrow () __attribute__((__noreturn__));
-
-// These facilitate code generation for recurring situations.
-extern "C" void __cxa_bad_cast () __attribute__((__noreturn__));
-extern "C" void __cxa_bad_typeid () __attribute__((__noreturn__));
-
// @@@ These are not directly specified by the IA-64 C++ ABI.
// Handles re-checking the exception specification if unexpectedHandler
diff --git a/libstdc++-v3/scripts/create_testsuite_files b/libstdc++-v3/scripts/create_testsuite_files
index f4a0bcd80e0..a427eef2db0 100755
--- a/libstdc++-v3/scripts/create_testsuite_files
+++ b/libstdc++-v3/scripts/create_testsuite_files
@@ -32,7 +32,7 @@ cd $srcdir
# This is the ugly version of "everything but the current directory". It's
# what has to happen when find(1) doesn't support -mindepth, or -xtype.
dlist=`echo [0-9][0-9]*`
-dlist="$dlist abi backward ext performance tr1 decimal"
+dlist="$dlist abi backward ext performance tr1 tr2 decimal"
find $dlist "(" -type f -o -type l ")" -name "*.cc" -print > $tmp.01
find $dlist "(" -type f -o -type l ")" -name "*.c" -print > $tmp.02
cat $tmp.01 $tmp.02 | sort > $tmp.1
diff --git a/libstdc++-v3/testsuite/18_support/50594.cc b/libstdc++-v3/testsuite/18_support/50594.cc
new file mode 100644
index 00000000000..047f4a732bf
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/50594.cc
@@ -0,0 +1,72 @@
+// { dg-options "-fwhole-program" }
+
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <new>
+#include <string>
+#include <cstdlib>
+#include <testsuite_hooks.h>
+
+bool user_new_called;
+bool user_delete_called;
+
+void* operator new(std::size_t n)
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ throw(std::bad_alloc)
+#endif
+{
+ user_new_called = true;
+
+ void* p = std::malloc(n);
+
+ if (!p)
+ throw std::bad_alloc();
+
+ return p;
+}
+
+void operator delete(void* p)
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ noexcept
+#else
+ throw()
+#endif
+{
+ user_delete_called = true;
+
+ std::free(p);
+}
+
+// libstdc++/50594
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ {
+ std::string s = "Hello World.";
+ }
+
+ VERIFY( user_new_called );
+ VERIFY( user_delete_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/bind/48698.cc b/libstdc++-v3/testsuite/20_util/bind/48698.cc
index a623735f3eb..87e5f238632 100644
--- a/libstdc++-v3/testsuite/20_util/bind/48698.cc
+++ b/libstdc++-v3/testsuite/20_util/bind/48698.cc
@@ -25,7 +25,7 @@
int f(int i);
// Don't want placeholders to interfere with a possibly-versioned namespace.
-int g()
+void g()
{
std::bind(f, std::placeholders::_6);
}
diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/pointer_to.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/pointer_to.cc
index 33c96e17b2a..1cfc98084ee 100644
--- a/libstdc++-v3/testsuite/20_util/pointer_traits/pointer_to.cc
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/pointer_to.cc
@@ -29,12 +29,14 @@ struct Ptr
static Ptr pointer_to(bool& b) { return Ptr{&b}; }
};
+bool operator==(const Ptr& l, const Ptr& r) { return l.value == r.value; }
+
void test01()
{
bool test = true;
- Ptr p __attribute__((unused)) {&test};
+ Ptr p{ &test };
- VERIFY( std::pointer_traits<Ptr>::pointer_to(test).value == &test );
+ VERIFY( std::pointer_traits<Ptr>::pointer_to(test) == p );
}
void test02()
diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
index a3abadf4622..b72553ba0f4 100644
--- a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
@@ -41,19 +41,3 @@ main()
test01();
return 0;
}
-
-// { dg-warning "note" "" { target *-*-* } 370 }
-// { dg-warning "note" "" { target *-*-* } 365 }
-// { dg-warning "note" "" { target *-*-* } 356 }
-// { dg-warning "note" "" { target *-*-* } 1103 }
-// { dg-warning "note" "" { target *-*-* } 1098 }
-// { dg-warning "note" "" { target *-*-* } 1089 }
-// { dg-warning "note" "" { target *-*-* } 485 }
-// { dg-warning "note" "" { target *-*-* } 479 }
-// { dg-warning "note" "" { target *-*-* } 468 }
-// { dg-warning "note" "" { target *-*-* } 841 }
-// { dg-warning "note" "" { target *-*-* } 1056 }
-// { dg-warning "note" "" { target *-*-* } 1050 }
-// { dg-warning "note" "" { target *-*-* } 342 }
-// { dg-warning "note" "" { target *-*-* } 292 }
-// { dg-warning "note" "" { target *-*-* } 224 }
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc b/libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc
new file mode 100644
index 00000000000..9bdc310aaaf
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc
@@ -0,0 +1,95 @@
+// { dg-require-namedlocale "de_DE" }
+
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <locale>
+#include <ext/pod_char_traits.h>
+
+#define mychar __gnu_cxx::character<unsigned short, int>
+
+namespace std
+{
+ template<> codecvt<mychar, char, mbstate_t>::~codecvt()
+ { }
+
+ template<>
+ codecvt<mychar, char, mbstate_t>::result
+ codecvt<mychar, char, mbstate_t>::
+ do_out(state_type&, const intern_type*, const intern_type*,
+ const intern_type*&, extern_type*, extern_type*,
+ extern_type*&) const
+ { return codecvt_base::ok; }
+
+ template<>
+ codecvt<mychar, char, mbstate_t>::result
+ codecvt<mychar, char, mbstate_t>::
+ do_in(state_type&, const extern_type*, const extern_type*,
+ const extern_type*&, intern_type*, intern_type*,
+ intern_type*&) const
+ { return codecvt_base::ok; }
+
+ template<>
+ codecvt<mychar, char, mbstate_t>::result
+ codecvt<mychar, char, mbstate_t>::
+ do_unshift(state_type&, extern_type*, extern_type*,
+ extern_type*&) const
+ { return noconv; }
+
+ template<>
+ int
+ codecvt<mychar, char, mbstate_t>::do_encoding() const
+ { return 0; }
+
+ template<>
+ bool
+ codecvt<mychar, char, mbstate_t>::do_always_noconv() const
+ { return false; }
+
+ template<>
+ int
+ codecvt<mychar, char, mbstate_t>::
+ do_length(state_type&, const extern_type*, const extern_type*,
+ size_t) const
+ { return 0; }
+
+ template<>
+ int
+ codecvt<mychar, char, mbstate_t>::do_max_length() const
+ { return 4; }
+}
+
+// libstdc++/50714
+void test01()
+{
+ using namespace std;
+
+ {
+ locale loc(locale::classic(),
+ new codecvt<mychar, char, mbstate_t>());
+ }
+ {
+ locale loc2(locale::classic(),
+ new codecvt_byname<mychar, char, mbstate_t>("de_DE"));
+ }
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
index f53082d1aa1..974821f0e52 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1499 }
+// { dg-error "no matching" "" { target *-*-* } 1549 }
#include <list>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
index f0af9715138..6683e78062d 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1455 }
+// { dg-error "no matching" "" { target *-*-* } 1505 }
#include <list>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
index 168d592361d..f3e70098ea0 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1455 }
+// { dg-error "no matching" "" { target *-*-* } 1505 }
#include <list>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
index 32bfd53e7c1..7e19c4205dc 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1455 }
+// { dg-error "no matching" "" { target *-*-* } 1505 }
#include <list>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/allocator/minimal.cc b/libstdc++-v3/testsuite/23_containers/vector/allocator/minimal.cc
new file mode 100644
index 00000000000..2d56884a436
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/allocator/minimal.cc
@@ -0,0 +1,45 @@
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++0x" }
+
+#include <vector>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::SimpleAllocator;
+
+template class std::vector<T, SimpleAllocator<T>>;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ typedef SimpleAllocator<T> alloc_type;
+ typedef std::allocator_traits<alloc_type> traits_type;
+ typedef std::vector<T, alloc_type> test_type;
+ test_type v(alloc_type{});
+ VERIFY( v.max_size() == traits_type::max_size(v.get_allocator()) );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
index 55b9096d768..00d18b74fd5 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1222 }
+// { dg-error "no matching" "" { target *-*-* } 1223 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
index 6ea2c6f1145..34c2ed1c6a8 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1152 }
+// { dg-error "no matching" "" { target *-*-* } 1153 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
index 75b5bd6d218..563def0e666 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1152 }
+// { dg-error "no matching" "" { target *-*-* } 1153 }
#include <vector>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
index d93de19d486..fec41a39fdb 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1263 }
+// { dg-error "no matching" "" { target *-*-* } 1264 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/requirements/base_classes.cc b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/requirements/base_classes.cc
index 5c7274579e0..ce946f6a419 100644
--- a/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/requirements/base_classes.cc
+++ b/libstdc++-v3/testsuite/24_iterators/istreambuf_iterator/requirements/base_classes.cc
@@ -1,7 +1,8 @@
// { dg-do compile }
// 1999-06-28 bkoz
-// Copyright (C) 1999, 2001, 2003, 2009 Free Software Foundation, Inc.
+// Copyright (C) 1999, 2001, 2003, 2009, 2010, 2011
+// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -31,7 +32,14 @@ void test01()
// Check for required base class.
typedef istreambuf_iterator<char> test_iterator;
typedef char_traits<char>::off_type off_type;
- typedef iterator<input_iterator_tag, char, off_type, char*, char&> base_iterator;
+
+ typedef iterator<input_iterator_tag, char, off_type, char*,
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ char>
+#else
+ char&>
+#endif
+ base_iterator;
istringstream isstream("this tag");
test_iterator r_it(isstream);
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc b/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc
index 4bbe5b11925..488e393d2a7 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc
@@ -18,21 +18,18 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-
#include <ios>
// Library defect report
//50. Copy constructor and assignment operator of ios_base
-class test_base : public std::ios_base { };
+class test_base : public std::ios_base { }; // { dg-error "within this context|deleted" }
void test01()
{
// assign
test_base io1;
test_base io2;
- io1 = io2;
+ io1 = io2; // { dg-error "synthesized|deleted" }
}
-// { dg-error "synthesized" "" { target *-*-* } 33 }
-// { dg-error "within this context" "" { target *-*-* } 26 }
-// { dg-error "is private" "" { target *-*-* } 791 }
-// { dg-error "operator=" "" { target *-*-* } 0 }
+
+// { dg-prune-output "include" }
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc b/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc
index 6f453736e87..22caadc6497 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc
@@ -18,21 +18,18 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-
#include <ios>
// Library defect report
//50. Copy constructor and assignment operator of ios_base
-struct test_base : public std::ios_base
+struct test_base : public std::ios_base // { dg-error "within this context|deleted" }
{ };
void test02()
{
// copy ctor
test_base io1;
- test_base io2 = io1;
+ test_base io2 = io1; // { dg-error "synthesized|deleted" }
}
-// { dg-error "within this context" "" { target *-*-* } 26 }
-// { dg-error "synthesized" "" { target *-*-* } 33 }
-// { dg-error "is private" "" { target *-*-* } 788 }
-// { dg-error "copy constructor" "" { target *-*-* } 0 }
+
+// { dg-prune-output "include" }
diff --git a/libstdc++-v3/testsuite/ext/codecvt/char-1.cc b/libstdc++-v3/testsuite/ext/codecvt/char-1.cc
index 733dff8a078..8e0d56f55a4 100644
--- a/libstdc++-v3/testsuite/ext/codecvt/char-1.cc
+++ b/libstdc++-v3/testsuite/ext/codecvt/char-1.cc
@@ -4,6 +4,7 @@
// 2000-08-22 Benjamin Kosnik <bkoz@cygnus.com>
// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
+// 2010, 2011
// Free Software Foundation
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -69,10 +70,14 @@ void test01()
char i_lit_base[50] __attribute__((aligned(__alignof__(int_type)))) =
{
- 0x00, 0x62, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20,
- 0x00, 0x70, 0x00, 0x65, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x20,
- 0x00, 0x6a, 0x00, 0x61, 0x00, 0x73, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e,
- 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x61, 0x00, 0xa0
+ char(0x00), char(0x62), char(0x00), char(0x6c), char(0x00), char(0x61),
+ char(0x00), char(0x63), char(0x00), char(0x6b), char(0x00), char(0x20),
+ char(0x00), char(0x70), char(0x00), char(0x65), char(0x00), char(0x61),
+ char(0x00), char(0x72), char(0x00), char(0x6c), char(0x00), char(0x20),
+ char(0x00), char(0x6a), char(0x00), char(0x61), char(0x00), char(0x73),
+ char(0x00), char(0x6d), char(0x00), char(0x69), char(0x00), char(0x6e),
+ char(0x00), char(0x65), char(0x00), char(0x20), char(0x00), char(0x74),
+ char(0x00), char(0x65), char(0x00), char(0x61), char(0x00), char(0xa0)
};
const int_type* i_lit = reinterpret_cast<int_type*>(i_lit_base);
diff --git a/libstdc++-v3/testsuite/ext/codecvt/char-2.cc b/libstdc++-v3/testsuite/ext/codecvt/char-2.cc
index b6bfde01e8a..81c42e25f06 100644
--- a/libstdc++-v3/testsuite/ext/codecvt/char-2.cc
+++ b/libstdc++-v3/testsuite/ext/codecvt/char-2.cc
@@ -4,6 +4,7 @@
// 2000-08-22 Benjamin Kosnik <bkoz@cygnus.com>
// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
+// 2010, 2011
// Free Software Foundation
//
// This file is part of the GNU ISO C++ Library. This library is free
@@ -69,10 +70,14 @@ void test02()
char i_lit_base[50] __attribute__((aligned(__alignof__(int_type)))) =
{
- 0x62, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00,
- 0x70, 0x00, 0x65, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x20, 0x00,
- 0x6a, 0x00, 0x61, 0x00, 0x73, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00,
- 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x61, 0x00, 0xa0, 0x00
+ char(0x62), char(0x00), char(0x6c), char(0x00), char(0x61), char(0x00),
+ char(0x63), char(0x00), char(0x6b), char(0x00), char(0x20), char(0x00),
+ char(0x70), char(0x00), char(0x65), char(0x00), char(0x61), char(0x00),
+ char(0x72), char(0x00), char(0x6c), char(0x00), char(0x20), char(0x00),
+ char(0x6a), char(0x00), char(0x61), char(0x00), char(0x73), char(0x00),
+ char(0x6d), char(0x00), char(0x69), char(0x00), char(0x6e), char(0x00),
+ char(0x65), char(0x00), char(0x20), char(0x00), char(0x74), char(0x00),
+ char(0x65), char(0x00), char(0x61), char(0x00), char(0xa0), char(0x00)
};
const int_type* i_lit = reinterpret_cast<int_type*>(i_lit_base);
diff --git a/libstdc++-v3/testsuite/ext/codecvt/wchar_t.cc b/libstdc++-v3/testsuite/ext/codecvt/wchar_t.cc
index 4040f876b1b..ae8e47be127 100644
--- a/libstdc++-v3/testsuite/ext/codecvt/wchar_t.cc
+++ b/libstdc++-v3/testsuite/ext/codecvt/wchar_t.cc
@@ -3,7 +3,8 @@
// 2000-08-23 Benjamin Kosnik <bkoz@cygnus.com>
-// Copyright (C) 2000, 2001, 2002, 2003, 2007, 2009 Free Software Foundation
+// Copyright (C) 2000, 2001, 2002, 2003, 2007, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -43,23 +44,35 @@ void test01()
int size = 23;
char e_lit_base[96] __attribute__((aligned(__alignof__(ext_type)))) =
{
- 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x61,
- 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x20,
- 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x61,
- 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x20,
- 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73,
- 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6e,
- 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x74,
- 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xa0
+ char(0x00), char(0x00), char(0x00), char(0x62), char(0x00), char(0x00),
+ char(0x00), char(0x6c), char(0x00), char(0x00), char(0x00), char(0x61),
+ char(0x00), char(0x00), char(0x00), char(0x63), char(0x00), char(0x00),
+ char(0x00), char(0x6b), char(0x00), char(0x00), char(0x00), char(0x20),
+ char(0x00), char(0x00), char(0x00), char(0x70), char(0x00), char(0x00),
+ char(0x00), char(0x65), char(0x00), char(0x00), char(0x00), char(0x61),
+ char(0x00), char(0x00), char(0x00), char(0x72), char(0x00), char(0x00),
+ char(0x00), char(0x6c), char(0x00), char(0x00), char(0x00), char(0x20),
+ char(0x00), char(0x00), char(0x00), char(0x6a), char(0x00), char(0x00),
+ char(0x00), char(0x61), char(0x00), char(0x00), char(0x00), char(0x73),
+ char(0x00), char(0x00), char(0x00), char(0x6d), char(0x00), char(0x00),
+ char(0x00), char(0x69), char(0x00), char(0x00), char(0x00), char(0x6e),
+ char(0x00), char(0x00), char(0x00), char(0x65), char(0x00), char(0x00),
+ char(0x00), char(0x20), char(0x00), char(0x00), char(0x00), char(0x74),
+ char(0x00), char(0x00), char(0x00), char(0x65), char(0x00), char(0x00),
+ char(0x00), char(0x61), char(0x00), char(0x00), char(0x00), char(0xa0)
};
const ext_type* e_lit = reinterpret_cast<ext_type*>(e_lit_base);
char i_lit_base[48] __attribute__((aligned(__alignof__(int_type)))) =
{
- 0x00, 0x62, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20,
- 0x00, 0x70, 0x00, 0x65, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6c, 0x00, 0x20,
- 0x00, 0x6a, 0x00, 0x61, 0x00, 0x73, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e,
- 0x00, 0x65, 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x61, 0x00, 0xa0
+ char(0x00), char(0x62), char(0x00), char(0x6c), char(0x00), char(0x61),
+ char(0x00), char(0x63), char(0x00), char(0x6b), char(0x00), char(0x20),
+ char(0x00), char(0x70), char(0x00), char(0x65), char(0x00), char(0x61),
+ char(0x00), char(0x72), char(0x00), char(0x6c), char(0x00), char(0x20),
+ char(0x00), char(0x6a), char(0x00), char(0x61), char(0x00), char(0x73),
+ char(0x00), char(0x6d), char(0x00), char(0x69), char(0x00), char(0x6e),
+ char(0x00), char(0x65), char(0x00), char(0x20), char(0x00), char(0x74),
+ char(0x00), char(0x65), char(0x00), char(0x61), char(0x00), char(0xa0)
};
const int_type* i_lit = reinterpret_cast<int_type*>(i_lit_base);
diff --git a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize_neg.cc b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize_neg.cc
index c5b2bd2e98f..e4c922af4f2 100644
--- a/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize_neg.cc
+++ b/libstdc++-v3/testsuite/ext/pb_ds/example/hash_resize_neg.cc
@@ -1,7 +1,8 @@
// { dg-do compile }
// -*- C++ -*-
-// Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011
+// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -60,4 +61,4 @@ int main()
h.resize(20); // { dg-error "required from" }
}
-// { dg-error "invalid" "" { target *-*-* } 187 }
+// { dg-prune-output "include" }
diff --git a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
index ba515b7fb6b..4e2d071b833 100644
--- a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
+++ b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
@@ -25,4 +25,4 @@
#include <vector>
-// { dg-error "multiple inlined namespaces" "" { target *-*-* } 256 }
+// { dg-error "multiple inlined namespaces" "" { target *-*-* } 258 }
diff --git a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
index 8642eb7eea6..19fa0e2cc79 100644
--- a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
+++ b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
@@ -58,6 +58,7 @@ if {[info exists tests_file] && [file exists $tests_file]} {
lappend subdirs "$srcdir/ext"
lappend subdirs "$srcdir/performance"
lappend subdirs "$srcdir/tr1"
+ lappend subdirs "$srcdir/tr2"
lappend subdirs "$srcdir/decimal"
verbose "subdirs are $subdirs"
diff --git a/libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc b/libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc
new file mode 100644
index 00000000000..30fc105c272
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc
@@ -0,0 +1,72 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <cassert>
+#include <unordered_set>
+#include <testsuite_performance.h>
+
+int main()
+{
+ using namespace __gnu_test;
+
+ time_counter time;
+ resource_counter resource;
+
+ start_counters(time, resource);
+
+ std::unordered_set<int> us;
+ for (int i = 0; i != 5000000; ++i)
+ us.insert(i);
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "Container generation", time, resource);
+
+ start_counters(time, resource);
+
+ for (int j = 100; j != 0; --j)
+ {
+ auto it = us.begin();
+ while (it != us.end())
+ {
+ if ((*it % j) == 0)
+ it = us.erase(it);
+ else
+ ++it;
+ }
+ }
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "Container erase", time, resource);
+
+ start_counters(time, resource);
+
+ us.insert(0);
+
+ for (int i = 0; i != 500; ++i)
+ {
+ auto it = us.begin();
+ ++it;
+ assert( it == us.end() );
+ }
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "Container iteration", time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
new file mode 100644
index 00000000000..ddd6d6fa38e
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+ namespace tr2
+ {
+ typedef short test_type;
+ template struct bases<test_type>;
+ }
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
new file mode 100644
index 00000000000..a62acffe89c
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+//
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+ // Check for required typedefs
+ typedef std::tr2::bases<int> test_type;
+ typedef test_type::type value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/value.cc b/libstdc++-v3/testsuite/tr2/bases/value.cc
new file mode 100644
index 00000000000..415e974a980
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/value.cc
@@ -0,0 +1,97 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+ bool test __attribute__((unused)) = true;
+
+ // 1
+ {
+ typedef std::tr2::bases<A>::type tl;
+ static_assert(tl::empty::value, "error");
+ }
+
+ // 2
+ {
+ typedef std::tr2::bases<B1>::type tl1;
+ typedef std::tr2::bases<B2>::type tl2;
+
+ // Sanity check w/ runtime.
+ bool eq = typeid(tl1) == typeid(tl2);
+ if (!eq)
+ throw std::logic_error("typelist not equal");
+
+ // Sanity check.
+ static_assert(tl1::empty::value != std::true_type::value, "!empty");
+ static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+ typedef tl1::first::type tl1_first;
+ typedef tl1::rest::type tl1_rest;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl2_rest;
+
+ eq = typeid(tl1_first) == typeid(tl2_first);
+ if (!eq)
+ throw std::logic_error("base not equal");
+
+ static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+ static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+ }
+
+ // 3
+ {
+ typedef std::tr2::bases<C>::type tl;
+
+ // Sanity check.
+ static_assert(tl::empty::value != std::true_type::value, "!empty");
+
+ typedef tl::first::type tl1_first;
+ typedef tl::rest::type tl2;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl3;
+ typedef tl3::first::type tl3_first;
+ typedef tl3::rest::type tl4;
+
+ bool eq = typeid(tl1_first) == typeid(tl2_first);
+ if (eq)
+ throw std::logic_error("bases are not equal");
+
+ eq = typeid(tl2_first) == typeid(tl3_first);
+ if (eq)
+ throw std::logic_error("bases are not equal");
+
+ static_assert(tl4::empty::value == std::true_type::value, "empty");
+ }
+
+}
+
+int main()
+{
+ test();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
new file mode 100644
index 00000000000..d7fb96aff01
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+ namespace tr2
+ {
+ typedef short test_type;
+ template struct direct_bases<test_type>;
+ }
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
new file mode 100644
index 00000000000..7d219ea3ffc
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+//
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+ // Check for required typedefs
+ typedef std::tr2::direct_bases<int> test_type;
+ typedef test_type::type value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/value.cc b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
new file mode 100644
index 00000000000..81d0269c525
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+ bool test __attribute__((unused)) = true;
+
+ // 1
+ {
+ typedef std::tr2::direct_bases<A>::type tl;
+ static_assert(tl::empty::value, "error");
+ }
+
+ // 2
+ {
+ typedef std::tr2::direct_bases<B1>::type tl1;
+ typedef std::tr2::direct_bases<B2>::type tl2;
+
+ // Sanity check w/ runtime.
+ bool eq = typeid(tl1) == typeid(tl2);
+ if (!eq)
+ throw std::logic_error("typelist not equal");
+
+ // Sanity check.
+ static_assert(tl1::empty::value != std::true_type::value, "!empty");
+ static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+ typedef tl1::first::type tl1_first;
+ typedef tl1::rest::type tl1_rest;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl2_rest;
+
+ eq = typeid(tl1_first) == typeid(tl2_first);
+ if (!eq)
+ throw std::logic_error("base not equal");
+
+ static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+ static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+ }
+
+ // 3
+ {
+ typedef std::tr2::direct_bases<C>::type tl;
+
+ // Sanity check.
+ static_assert(tl::empty::value != std::true_type::value, "!empty");
+
+ typedef tl::first::type tl1_first;
+ typedef tl::rest::type tl2;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl3;
+
+ bool eq = typeid(tl1_first) == typeid(tl2_first);
+ if (eq)
+ throw std::logic_error("bases are not equal");
+
+ static_assert(tl3::empty::value == std::true_type::value, "empty");
+ }
+
+}
+
+int main()
+{
+ test();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/headers/all.cc b/libstdc++-v3/testsuite/tr2/headers/all.cc
new file mode 100644
index 00000000000..096cdc06248
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/headers/all.cc
@@ -0,0 +1,24 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <tr2/dynamic_bitset>
+#include <tr2/bool_set>
+#include <tr2/ratio>
diff --git a/libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc b/libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc
new file mode 100644
index 00000000000..b114327bb20
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc
@@ -0,0 +1,26 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+
+namespace gnu
+{
+ using namespace std::tr2;
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index f1f5ad66347..9e6837e9b52 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -204,6 +204,7 @@ check_version(symbol& test, bool added)
known_versions.push_back("CXXABI_1.3.3");
known_versions.push_back("CXXABI_1.3.4");
known_versions.push_back("CXXABI_1.3.5");
+ known_versions.push_back("CXXABI_1.3.6");
known_versions.push_back("CXXABI_LDBL_1.3");
}
compat_list::iterator begin = known_versions.begin();
diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h
index 57a5a8ae896..c0b8ee3be9b 100644
--- a/libstdc++-v3/testsuite/util/testsuite_allocator.h
+++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h
@@ -256,7 +256,11 @@ namespace __gnu_test
typedef Tp& reference;
typedef const Tp& const_reference;
typedef Tp value_type;
-
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ typedef std::true_type propagate_on_container_swap;
+#endif
+
template<typename Tp1>
struct rebind
{ typedef uneq_allocator<Tp1> other; };
@@ -386,6 +390,8 @@ namespace __gnu_test
typedef std::integral_constant<bool, Propagate> trait_type;
public:
+ // default allocator_traits::rebind_alloc would select
+ // uneq_allocator::rebind so we must define rebind here
template<typename Up>
struct rebind { typedef propagating_allocator<Up, Propagate> other; };
@@ -403,6 +409,14 @@ namespace __gnu_test
propagating_allocator(const propagating_allocator&) noexcept = default;
+ propagating_allocator&
+ operator=(const propagating_allocator& a) noexcept
+ {
+ static_assert(Propagate, "assigning propagating_allocator<T, true>");
+ propagating_allocator(a).swap_base(*this);
+ return *this;
+ }
+
template<bool P2>
propagating_allocator&
operator=(const propagating_allocator<Tp, P2>& a) noexcept
@@ -433,6 +447,32 @@ namespace __gnu_test
{ return Propagate ? *this : propagating_allocator(); }
};
+ // Class template supporting the minimal interface that satisfies the
+ // Allocator requirements, from example in [allocator.requirements]
+ template <class Tp>
+ struct SimpleAllocator
+ {
+ typedef Tp value_type;
+
+ SimpleAllocator() { }
+
+ template <class T>
+ SimpleAllocator(const SimpleAllocator<T>& other) { }
+
+ Tp *allocate(std::size_t n)
+ { return std::allocator<Tp>().allocate(n); }
+
+ void deallocate(Tp *p, std::size_t n)
+ { std::allocator<Tp>().deallocate(p, n); }
+ };
+
+ template <class T, class U>
+ bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&)
+ { return true; }
+ template <class T, class U>
+ bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&)
+ { return false; }
+
#endif
template<typename Tp>
diff --git a/libstdc++-v3/testsuite/util/testsuite_rvalref.h b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
index 2234e8112a9..73c70e06990 100644
--- a/libstdc++-v3/testsuite/util/testsuite_rvalref.h
+++ b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
@@ -255,6 +255,9 @@ namespace __gnu_test
{ throw 1; }
throwing_move_constructor(const throwing_move_constructor&) = default;
+
+ throwing_move_constructor&
+ operator=(const throwing_move_constructor&) = default;
};
} // namespace __gnu_test
diff --git a/libstdc++-v3/testsuite/util/testsuite_tr1.h b/libstdc++-v3/testsuite/util/testsuite_tr1.h
index 94207a6e63d..f0638960b27 100644
--- a/libstdc++-v3/testsuite/util/testsuite_tr1.h
+++ b/libstdc++-v3/testsuite/util/testsuite_tr1.h
@@ -68,13 +68,14 @@ namespace __gnu_test
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
- template<template<typename...> class Property, typename... Types>
+ template<template<typename...> class Property,
+ typename Type1, typename... Types>
bool
- test_property(typename Property<Types...>::value_type value)
+ test_property(typename Property<Type1, Types...>::value_type value)
{
bool ret = true;
- ret &= Property<Types...>::value == value;
- ret &= Property<Types...>::type::value == value;
+ ret &= Property<Type1, Types...>::value == value;
+ ret &= Property<Type1, Types...>::type::value == value;
return ret;
}
#endif